redis知识点(二)
1.主从复制优化
- redis主从同步分为全量同步和增量同步。且主从同步是非阻塞的,即同步过程不会影响主服务器的正常访问。
- 主节点重启会导致全量同步,从节点重启只会导致增量同步。
1.1全量复制过程

- 主从节点建立连接,验证身份后,从节点想主节点发送PSYNC命令。
- 主节点向从节点发送FULLRESYNC命令,包括master_replid(runID)和offset
- 从节点保存主节点信息
- 主节点执行BGSAVE保存RDB文件,同时记录新的记录到buffer中
- 主节点发送RDB文件给从节点
- 主节点将新收到buffer中的记录发送至从节点
- 从节点删除本机的旧数据
- 从节点加载RDB
- 从节点同步主节点的buffer信息
全量复制发生在下面情况
- 从节点首次连接主节点(无master_replid/run_id)
- 从节点的复制偏移量不在复制积压缓冲区内
- 从节点无法连接主节点超过一定的时间
1.2增量复制过程

- 在主从复制首次完成全量同步之后再次需要同步时,从服务器只要发送当前的offset位置(类似于MySQL的binlog的位置)给主服务器,然后主服务器根据相应的位置将之后的数据(包括写在缓冲区的积压数据)发送给从服务器,再次将其保存到从节点内存即可
1.3主从同步完整过程
主从同步完整过程如下:
- slave发起连接master,验证通过后,发送PSYNC命令
- master接收到PSYNC命令后,执行BGSAVE命令将全部数据保存至RDB文件中,并将后续发生的写操作记录至buffer中
- master向所有slave发送RDB文件
- master向所有slave发送后续记录在buffer中写操作
- slave收到快照文件后丢弃所有旧数据
- slave加载收到的RDB到内存
- slave 执行来自master接收到的buffer写操作
- 当slave完成全量复制后,后续master只会先发送slave_repl_offset信息
- 以后slave比较自身和master的差异,只会进行增量复制的数据即可
1.4避免全量复制
- 第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),业务低峰时进行全量
- 节点master_replid或RUN_ID不匹配:主节点重启会导致master_replid或RUN_ID变化,可能会触发全量复制,可以利用config命令动态修改配置,故障转移例如哨兵或集群选举新的主节点也不会全量复制,而从节点重启动,不会导致全量复制,只会增量复制
- 复制挤压缓冲区不足:当主节点生成的新数据大于缓冲区大小,从节点恢复和主机节点连接后,会导致全量复制。解决方法:将repl-backlog-size调大
1.5避免复制风暴
-
单主节点复制风暴:当主节点重启,多从节点复制;解决方法:跟换复制拓扑。级联复制。
-
单机器多实例复制风暴。机器宕机后,大量全量复制。解决方法:主节点分散多机器

1.6常见主从复制故障
-
主从硬件和软件配置不一致
-
主从节点的maxmemory不一致,主节点内存大于从节点内存,主从复制可能丢失数据
-
rename-command 命令不一致,如在主节点启用flushdb,从节点禁用此命令,结果在master节点执行flushdb后,导致slave节点不同步
-
-
slave节点配置的master密码错误
-
redis的版本不一致,主从复制的所有节点应该使用相同的版本。
-
如果开启了安全模式,并且没有设置bind地址和密码,会导致无法远程连接
2.redis哨兵sentinel

- 客户从sentinel获取Redis信息。
- Sentinel是一个分布式系统,即需要在多个节点上各自同时运行一个sentinel进程,Sentienl 进程通过流言协议(gossip protocols)来接收关于Master是否下线状态,并使用投票协议(Agreement Protocols)来决定是否执行自动故障转移,并选择合适的Slave作为新的Master
2.1sentinel中的三个定时任务
-
每10秒每个sentinel对master和slave执行info——发现slave节点,确认主从关系
-
每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
——通过sentinel__:hello频道交互;交互对节点的“看法”和自身信息
-
每1秒每个sentinel对其他sentinel和redis执行ping
2.2搭建哨兵系统
- 哨兵的前提是实现了主从复制,包括master和slave在内的所有节点的 masterauth 和requirepassslave 密码都必须相同
- 所有主节点的 redis.conf 中关健配置
#在所有主从节点执行
#基于包安装
yum -y install redis
apt -y install redis redis-sentinel
#所有节点的masterauth和requirepass必须相同
[root@centos8 ~]#vim /etc/redis.conf
bind 0.0.0.0
masterauth "123456"
requirepass "123456"
#在所有从节点执行
[root@centos8 ~]#echo "replicaof 10.0.0.8 6379" >> /etc/redis.conf
#在所有主从节点执行
[root@centos8 ~]#systemctl enable –now redis
- 查看主节点状态
#redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface
may not
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.0.0.28,port=6379,state=online,offset=112,lag=1
slave1:ip=10.0.0.18,port=6379,state=online,offset=112,lag=0
- 配置slave1
>REPLICAOF 10.0.0.8 6379
ok
>CONFIG SET masterauth "123456"
ok
>INFO replication
role:slave
master_host:10.0.0.8
master_port:6379
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_repl_offset:140
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:8fdca730a2ae48fb9c8b7e739dcd2efcc76794f3
master_replid2:0000000000000000000000000000000000000000
- 配置slave2
>REPLICAOF 10.0.0.8 6379
OK
>CONFIG SET masterauth "123456"
ok
>INFO replication
role:slave
master_host:10.0.0.8
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:182
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:8fdca730a2ae48fb9c8b7e739dcd2efcc76794f3
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:182
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:168
-
编辑哨兵配置
- Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持.默认监听在26379/tcp端口.
- 哨兵服务可以和Redis服务器分开部署在不同主机,但为了节约成本一般会部署在一起
- 所有redis节点使用相同的以下示例的配置文件
cp redis-7.0.5/sentinel.conf /apps/redis/etc/sentinel.conf
chown redis.redis /apps/redis/etc/sentinel.conf#编译安装修改配置文件
protected-mode no #包安装时默认为yes,此处要修改为no
port 26379
daemonize no
pidfile "/apps/redis/run/redis-sentinel.pid"
logfile "/apps/redis/log/redis-sentinel.log"
dir "/tmp"
sentinel monitor mymaster 10.0.0.102 6379 2
#mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口
#2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有sentinel节点(一般总数是>=3的 奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,取整为2,是master的ODOWN客观下线的依据#mymaster集群中master的密码,注意此行要在上面行的下面,注意:要求这组redis主从复制所有节点的密
码是一样的
sentinel down-after-milliseconds mymaster 3000
#判断mymaster集群中所有节点的主观下线(SDOWN)的时间,单位:毫秒,建议3000
acllog-max-len 128
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames no
sentinel announce-hostnames no#包安装修改配置文件
vim /etc/redis-sentinel.conf
bind 0.0.0.0
port 26379
daemonize yes
pidfile "redis-sentinel.pid"
logfile "sentinel_26379.log"
dir "/tmp" #工作目录
sentinel monitor mymaster 10.0.0.8 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
#发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力
sentinel failover-timeout mymaster 180000
#所有slaves指向新的master所需的超时时间,单位:毫秒
sentinel deny-scripts-reconfig yes #禁止修改脚本
logfile /var/log/redis/sentinel.log -
三个哨兵服务器配置
sentinel monitor mymaster 10.0.0.8 6379 2 #修改此行
sentinel auth-pass mymaster 123456 #增加此行
sentinel down-after-milliseconds mymaster 3000 #修改此行
#注意此行自动生成必须唯一,一般不需要修改,如果相同则修改此值需重启redis和sentinel服务
sentinel myid 50547f34ed71fd48c197924969937e738a39975b
- 启动哨兵服务
[root@redis-master ~]systemctl enable –now redis-sentinel.service
[root@redis-slave1 ~]systemctl enable –now redis-sentinel.service
[root@redis-slave2 ~]systemctl enable –now redis-sentinel.service
-
查看当前sentinel状态
在sentinel状态中尤其是最后一行,涉及到masterIP是多少,有几个slave,有几个sentinels,必须是符合全部服务器数量
#redis-cli -p 26379
127.0.0.1:26379> INFO sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=10.0.0.8:6379,slaves=2,sentinels=3 #两个slave,三个sentinel服务器,如果sentinels值不符合,检查myid可能冲突
2.3sentinel运维
vim /etc/redis.conf
replica-priority 10 #指定优先级,值越小sentinel会优先将之选为新的master,默认值为100,如果为0,表示只当从节点
#或者动态修改
127.0.0.1:6379> CONFIG GET replica-priority
1) "replica-priority"
2) "100"
127.0.0.1:6379> CONFIG SET replica-priority 99
OK
127.0.0.1:6379> CONFIG GET replica-priority
1) "replica-priority"
2) "99"
2.4应用程序连接sentinel
- Java连接
#jedis/pom.xml 配置连接redis
<properties>
<redis–
hosts>localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383
,localhost:6384,localhost:6385</redis–hosts>
<sentinel–hosts>localhost:26379,localhost:26380,localhost:26381</sentinel–hosts>
<cluster–hosts>localhost:7379,localhost:7380,localhost:7381,localhost:7382,localhost:7383
,localhost:7384,localhost:7385</cluster–hosts>
<github.global.server>github</github.global.server>
</properties>
- python连接
apt -y install python3-redis
cat sentinel_test.py
#!/usr/bin/python3
import redis
from redis.sentinel import Sentinel
#连接到哨兵服务(主机也可以使用域名)
sentinel = sentinel([('10.0.0.8',26379),
('10.0.0.18',26379),
('10.0.0.28',26379)],
socket_timeout=0.5)
redis_auth_pass = '123456'
#mymaster是配置哨兵模式的redis集群名称,此为默认值
#获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)
#获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(master)
#获取主服务器进行写入
master = sentinel.master_for('mymaster', socket_timeout=0.5,
password=redis_auth_pass, db=0)
w_ret = master.set('name', 'wang')
#输出:True
#获取从服务器进行读取(默认是round-roubin)
slave = sentinel.slave_for('mymaster', socket_timeout=0.5,
password=redis_auth_pass, db=0)
r_ret = slave.get('name')
print(r_ret)
#输出:wang
#给权限
chmod +x sentinel_test.py
#运行脚本
./sentinel_test.py
网硕互联帮助中心





评论前必须登录!
注册