架构
OS:Centos6.8
Redis01:172.17.100.130(sentinel-1,sentinel-2)
Redis02:172.17.100.131(sentinel-3)
前置条件
yum install -y gcc openssl libtool
部署Redis(主库)
wget http://download.redis.io/releases/redis-4.0.11.tar.gz
tar -xf redis-4.0.11.tar.gz
cd redis-4.0.11
make
mkdir -p /opt/redis/sbin
mkdir -p /opt/redis/bin –p
mkdir -p /data/redis/redis6379/
cp redis.conf /data/redis/redis6379/6379.conf
cd src
cp redis-se* /opt/redis/sbin/
cp redis-check-aof /opt/redis/bin/
cp redis-cli /opt/redis/bin/
echo "export PATH=\$PATH:/opt/redis/sbin/:/opt/redis/bin/" >> /etc/profile
source /etc/profile
#这样操作之后redis只是有一些基本的功能,如果想做测试的话,将无法完成,如果想拥有全部的功能,可以执行下面的操作
#cd redis-4.0.11
#cp -r src /opt/redis/
#建议将redis-4.0.11文件夹改名保存
#编辑配置参数
mv /data/redis/redis6379/6379.conf /data/redis/redis6379/redis_conf.bak
vim /data/redis/redis6379/6379.conf
#是否在后台运行
daemonize yes
#pid文件路径
pidfile "/var/run/redis.pid"
#端口
port 6379
#密码
requirepass "password"
#主(从)节点密码
masterauth "password"
#
tcp-backlog 511
#客户端连接超时时间
timeout 0
#
tcp-keepalive 0
#log等级,生产环境建议notice
loglevel notice
#logfile路径
logfile "/data/redis/6379.log"
#数据库个数
databases 16
#redis进行数据库镜像的频率
#900秒内有1个key发生变化时(进行备份)
save 900 1
#300秒内有10个key发生变化时(进行备份)
save 300 10
#10000秒内有60个key发生变化时(进行备份)
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "6379.rdb"
#redis路径
dir "/data/redis/redis6379"
slave-serve-stale-data yes
#从库只读
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
#最大同时连接数
maxclients 10000
#redis能够使用的最大内存,当内存满了后,如果还收到set命令,redis将剔除设置过expire信息的key
maxmemory 1G
#最大内存淘汰策略
#volatile-lru:从已设置过期时间的内存数据集中挑选最近最少使用的数据 淘汰
#volatile-ttl: 从已设置过期时间的内存数据集中挑选即将过期的数据 淘汰
#volatile-random:从已设置过期时间的内存数据集中任意挑选数据 淘汰
#allkeys-lru:从内存数据集中挑选最近最少使用的数据 淘汰
#allkeys-random:从数据集中任意挑选数据 淘汰
#no-enviction(驱逐):禁止驱逐数据(默认)
maxmemory-policy volatile-lru
#开启appendonly后,redis会把接收到的每一次写操作都追加到appendonly.aof文件中
appendonly yes
#appendonly.aof的名字
appendfilename "6379.aof"
#同步频率,对写操作进行累积,每秒同步一次
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
#从库不需要密码就能访问
#protected-mode no
#redis-server只接收来自该IP的请求
bind 0.0.0.0
#bind 127.0.0.1
# Generated by CONFIG REWRITE
#当redis运行后(特别是主从),conf文件也会被修改,因此对初始文件进行备份
cp 6379.conf 6379.conf.bak
系统参数配置
sed -i -r '/vm.overcommit_memory*/d' /etc/sysctl.conf
sed -i -r '/vm.swappiness*/d' /etc/sysctl.conf
echo "vm.overcommit_memory =1">>/etc/sysctl.conf
echo "vm.swappiness = 1" >>/etc/sysctl.conf
/sbin/sysctl -q -p /etc/sysctl.conf
sed -i -r '/redis soft nofile.*/d' /etc/security/limits.conf
sed -i -r '/redis hard nofile.*/d' /etc/security/limits.conf
echo "redis soft nofile 288000" >>/etc/security/limits.conf
echo "redis hard nofile 288000" >>/etc/security/limits.conf
sed -i -r '/redis soft nproc.*/d' /etc/security/limits.conf
sed -i -r '/redis hard nproc.*/d' /etc/security/limits.conf
echo "redis soft nproc unlimited">>/etc/security/limits.conf
echo "redis hard nproc unlimited">>/etc/security/limits.conf
#(单机验证)启动
redis-server /data/redis/redis6379/6379.conf
#关闭
redis-cli shutdown
Redis从库部署
安装方式和主库一致,主要修改conf
wget http://download.redis.io/releases/redis-4.0.11.tar.gz
tar -xf redis-4.0.11.tar.gz
cd redis-4.0.11
make
mkdir -p /opt/redis/sbin
mkdir -p /opt/redis/bin –p
mkdir -p /data/redis/redis6380/
cp redis.conf /data/redis/redis6380/6380.conf
cd src
cp redis-se* /opt/redis/sbin/
cp redis-check-aof /opt/redis/bin/
cp redis-cli /opt/redis/bin/
echo "export PATH=\$PATH:/opt/redis/sbin/:/opt/redis/bin/" >> /etc/profile
source /etc/profile
修改系统参数
sed -i -r '/vm.overcommit_memory*/d' /etc/sysctl.conf
sed -i -r '/vm.swappiness*/d' /etc/sysctl.conf
echo "vm.overcommit_memory =1">>/etc/sysctl.conf
echo "vm.swappiness = 1" >>/etc/sysctl.conf
/sbin/sysctl -q -p /etc/sysctl.conf
sed -i -r '/redis soft nofile.*/d' /etc/security/limits.conf
sed -i -r '/redis hard nofile.*/d' /etc/security/limits.conf
echo "redis soft nofile 288000" >>/etc/security/limits.conf
echo "redis hard nofile 288000" >>/etc/security/limits.conf
sed -i -r '/redis soft nproc.*/d' /etc/security/limits.conf
sed -i -r '/redis hard nproc.*/d' /etc/security/limits.conf
echo "redis soft nproc unlimited">>/etc/security/limits.conf
echo "redis hard nproc unlimited">>/etc/security/limits.conf
#把主库的6379.conf传输到从库节点上,并修改名字为6380.conf
scp 172.17.100.130:/data/redis/redis6379/6379.conf /data/redis/redis6380/6380.conf
cd /data/redis/redis6380/
sed -i 's/6379/6380/g' 6380.conf
#搭建主从,除了修改端口以外,主要是增加下面这句slaveof
echo “slaveof 172.17.100.130 6379” >> 6380.conf
#主从的验证
登录从库
info replication
master_link_status为up即显示主从同步状态正常
PS:
如果测试环境不想配置密码,那么在主从的配置文件里要开启这个protected-mode no
在此次实验中,我们在配置里面写入了密码,所以要注释掉配置protected-mode no这句
至此主从redis配置完成
防火墙设置
主库
iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
iptables -I INPUT -p tcp --dport 16379 -j ACCEPT
iptables -I INPUT -p tcp --dport 26379 -j ACCEPT
service iptables save
从库
iptables -I INPUT -p tcp --dport 6380 -j ACCEPT
iptables -I INPUT -p tcp --dport 26380 -j ACCEPT
service iptables save
测试主从是否能配置成功
#首先开启主库
redis-server /data/redis/redis6379/6379.conf
#然后开启从库
redis-server /data/redis/redis6380/6380.conf
#登陆主库,进行一波操作
redis-cli -p 6379
keys *
set cnvex 'mysql-dba'
get cnvex
结果显示:"mysql-dba"
到从库上查看
redis-cli -p 6380
get cnvex
结果显示:"mysql-dba"
证明主库的数据已经传到从库上,主从配置成功
哨兵的配置
主库
mkdir -p /data/redis/{sentinel-1,sentinel-2}
cd /data/redis
vim sentinel.conf
daemonize yes
#bind 0.0.0.0
port 16379
dir "/data/redis/sentinel-1"
loglevel notice
logfile "/data/redis/sentinel-1.log"
#sentinel monitor mymaster 172.17.100.130 6379 2
sentinel monitor mymaster 172.17.100.130 6379 1
#配置mymaster的密码
sentinel auth-pass mymaster beacon
#5秒中mymaster没反应,则认为mymaster宕机
sentinel down-after-milliseconds mymaster 5000
#mymaster超过10秒仍然为宕机状态,则执行failover
sentinel failover-timeout mymaster 10000
#这个参数必须写,不写会影响failover
protected-mode no
#执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步
#sentinel config-epoch mymaster 1
由于哨兵启动后,conf文件也会被修改,所以建议对原始文件进行备份
此次实验,sentinel.conf就是我的原始文件
将其拷贝成sentinel-1.conf、sentinel-2.conf、sentinel-3.conf并修改文件中响应的字段进行匹配(主要是改端口,log名等等)
1和2放在主库130上,3放到从库131上,分别启动即完成了本次哨兵的搭建
启动哨兵
在主从库上分别启动哨兵
redis-sentinel /data/redis/sentinel-1.conf
redis-sentinel /data/redis/sentinel-2.conf
redis-sentinel /data/redis/sentinel-3.conf
关于conf和log
redis的conf
此次设定的是6379为主库,6380为从库;
正常启动情况下,6379.conf和6380.conf里面的内容不会有不同
但是在发生failover的情况下,原本出现在6380.conf里面的 “slaveof 172.17.100.130 6379” 会消失
而6379.conf最底下会出现 “slaveof 172.17.100.131 6380”
简言之,从库的conf下会自动出现slaveof语句
sentinel的conf
发2张图对比一下从库sentinel.conf前后的变化
图1为原始conf
图2为启动之后的conf
配置中列出了该sentinel的myid,当前的epoch值,以及除自己之外的其他几个哨兵(以及他们的myid)
关于epoch,哨兵启动后都会同步同一个epoch值,当发生切换(成功/失败)时,epoch值+1,如果一直切换失败,这个epoch值会不停的增长(如下图)
sentinel自动切换实验
主库
ps -ef|grep redis,kill掉redis-server对应的进程号
查看哨兵的log可以发现哨兵集群首先在kill掉主进程大约5秒钟之后将状态改为odown
生成新的epoch 17
开始选举投票,并执行一系列的failover准备
在51秒553完成切换,将主库由130 switch-master到131上
在56秒579的时候,将130变更为131的从库
从库这边的log如下
在主库上,重新拉起redis-server
log显示sentinel在第一时间判定130的redis-server为-sdown,之后将其连接为131的从库
此时的6379.conf末尾已经写入了slaveof信息
131并不会将主库还给130,而是自己继续做主库
将131的redis-server杀掉
上面的情况又会再次复现,130重新成为主库
实验中遇到的问题
问题1
主要是哨兵配置中的那个
protected-mode no
不一定必须配置成no,但是这个参数一定要配置
我试过注释掉这个参数,会发生无法切换的问题
问题2
之前在网上爬文,看到某些文章在下图里面配置数不为1,大概意思是需要多个哨兵统一,才会发生切换,但实际中我有3个哨兵,配置成1就能很好的完成切换任务,反而是配置成2之后,会遇到切换的问题
目前此处没有深究2者的差异,后续再来填坑