Redis:Replication实现主从复制,读写分离(4)
一、概念
为了避免服务器单点故障,导致Redis服务不可用,通常将数据复制多个副本保存在不同的服务器上。这样即使其中一台服务器出现故障,其他服务器依然可以继续服务。
Redis提供的高可用方案包括:
主从复制、哨兵模式的主从复制、集群
这里主要是讲解的第一种模式。
二、原理
一般是一主多从模式架构大概如下:
Redis的复制分为三个阶段:
复制初始化阶段、数据同步阶段、命令传播阶段
1)复制初始化阶段
当执行完slaveof masterip port 命令时候,从库根据指明的master节点ip和port向主库发起socket连接,主库收到socket连接之后将连接信息保存,此时连接建立;
当socket连接建立完成以后,从库向主库发送ping命令,以确认主库是否可用,此时的结果返回如果是PONG则代表主库可以用,否则可能出现超时或者主库此时在处理其他任务阻塞那么此时从库将断开socket连接,然后进行重试;
如果主库连接设置了密码,则从库需要设置masterauth参数,此时从库会发送auth命令,命令格式为“auth + 密码”进行密码验证,其中密码为masterauth参数配置的密码,需要注意的是如果主库设置了密码验证,从库未配置masterauth参数则报错,socket连接断开。
当身份验证完成以后,从节点发送自己的监听端口,主库保存其端口信息,此时进入下一个阶段:数据同步阶段。
2)数据同步阶段
主库和从库都确认对方信息以后,便可开始数据同步,此时从库向主库发送psync命令(需要注意的是redis4.0版本对2.8版本的psync做了优化,后续会进行说明),主库收到该命令后判断是进行增量复制还是全量复制,然后根据策略进行数据的同步,当主库有新的写操作时候,此时进入复制第三阶段:命令传播阶段。
3)命令传播阶段
当数据同步完成以后,在此后的时间里主从维护着心跳检查来确认对方是否在线,每隔一段时间(默认10秒,通过repl-ping-slave-period参数指定)主节点向从节点发送PING命令判断从节点是否在线,而从节点每秒1次向主节点发送REPLCONF ACK命令,命令格式为:REPLCONF ACK {offset},其中offset指从节点保存的复制偏移量,作用一是汇报自己复制偏移量,主节点会对比复制偏移量向从节点发送未同步的命令,作用二在于判断主节点是否在线,从库接送命令并执行,最终实现与主库数据相同。
三、实践
这里以一台Linux服务器上开启3个实例,做主从复制架构的演示。
主库:127.0.0.1 6379
从库:127.0.0.1 6380 127.0.0.1 6381
搭建步骤:
1)将redis.conf文件拷贝三分,命令最好有显示区别, 我这里采用名字为 6379.conf、 6380.conf、 6381.conf;
#建立三个redis目录
mkdir -p /opt/db/{redis6379,redis6380,redis6381}
#从源码中拷贝配置文件
cp redis-stable/redis.conf /opt/db/redis6379/6379.confcp redis-stable/redis.conf /opt/db/redis6380/6380.confcp redis-stable/redis.conf /opt/db/redis6381/6381.conf
2) 分别修改三个文件的ip(默认127.0.0.1可以不用修改)、端口(尽量和配置文件一致)、pid文件,日志文件,持久化数据目录(dir)、后台运行(daemonize yes);
6379.conf
daemonize yes #修改redis为后台运行模式pidfile /var/run/redis_6379.pid #修改运行的redis实例的pid,不能重复logfile "/opt/db/redis6379/6379.log" #指明日志文件dir "/opt/db/redis6379" #工作目录,存放持久化数据的目录bind 127.0.0.1 #监听地址,如果是单机多个示例可以不用修改port 6379 #监听端口,保持和配置文件名称端口一致
6380.conf
daemonize yes #修改redis为后台运行模式pidfile /var/run/redis_6380.pid #修改运行的redis实例的pid,不能重复logfile "/opt/db/redis6380/6380.log" #指明日志文件dir "/opt/db/redis6380" #工作目录,存放持久化数据的目录bind 127.0.0.1 #监听地址,如果是单机多个示例可以不用修改port 6380 #监听端口,保持和配置文件名称端口一致
6381.conf
daemonize yes #修改redis为后台运行模式pidfile /var/run/redis_6381.pid #修改运行的redis实例的pid,不能重复logfile "/opt/db/redis6379/6381.log" #指明日志文件dir "/opt/db/redis6381" #工作目录,存放持久化数据的目录bind 127.0.0.1 #监听地址,如果是单机多个实例可以不用修改使用127.0.0.1port 6381 #监听端口,保持和配置文件名称端口一致
3) 使用启动命令脚本启动每个redis服务;
redis-server /opt/db/redis6379/6379.confredis-server /opt/db/redis6380/6380.confredis-server /opt/db/redis6381/6381.conf
4) 设置主从关系、验证主从同步;
登录从服务器1
redis-cli -p 6380
#slaveof 127.0.0.1 6379#config rewrite#exit
登录从服务器2
redis-cli -p 6381
#slaveof 127.0.0.1 6379#config rewrite#exit
验证主从关系:
登录6380和6381
redis-cli -p 6380
#info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:953
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:033a29b5c04a79d2a43ae41d0fa2df41369745ec
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:953
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:29
repl_backlog_histlen:925
登录主服务器6379
redis-cli -p 6379
#info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6382,state=online,offset=168,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=168,lag=1
master_replid:033a29b5c04a79d2a43ae41d0fa2df41369745ec
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:168
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:168
测试数据同步:
6379下set数据
#set name user100
6380/6381下查看
#keys *"name"
则表示同步成功!
参考: