1.主从复制
说到分布式高可用,必然少不了复制,一来是为了做个冗余备份防止数据丢失,二来还可以达到分流来提高性能的目的。下面全部用M来表示Master(主服务器),用S来表示Slave(从服务器)
那么redis的复制是怎么实现的呢?啥也不说了,先看图:
Replication ID, offset
不好意思,没有图~哈哈~~看个表凑合吧
每个M都有上面这两个属性,Replication ID是M的唯一标识。offset是要发送命令流的字节数,简单来说,只要客户端有更新操作,这个offset就会增加。就算没有S,这个偏移量也是自动增长的。下面就是通过offset来实现部分复制的详细说明:
- S带上当前offset-s请求M进行复制
- M判断请求有效,offset_m - offset_s计算偏移,然后给S发送差异部分和offset_m
- S同步数据,更新offset_s = offset_m
redis默认使用高性能的异步复制,S会异步向M确认收到的数据
复制的机制和特点:
- 当M和S连接良好时,S定时请求M进行复制,M向S发送命令流来保持同步
- 当M和S由于网络问题或者超时导致断开连接,S会尝试重新连接,执行部分同步
- 当部分同步不可能时,S要求完全重新同步。 M需要创建完整的数据快照发送给S
- 一个M可以有多个S
- S也可以当做一个M供其他S进行复制
- 复制在M端是非阻塞的,也就是M向S复制的过程中,M的查询不受影响
- 复制在S端也基本上是非阻塞的,初始化同步的时候,S可以提供旧数据来使查询不受影响,同步开始时,S将会阻塞连接不提供查询服务(非常大的数据也只需要短短几秒就同步完了),旧数据将会被删除,新数据将会被载入
- 可以把耗时查询放到S上面来提高主机的性能
- 可以使用复制来避免M持久化带来的开销,让一个S来持久化,但是应该避免M重启,因为M重启之后数据是空的,这时候如果同步的话S的数据也变成空了。就算是用redis的sentinel实现的高可用方案,也不要把持久化关了,说不定sentinel还没来得及检测到故障,M就已经宕机然后重启了。为了避免这种情况,建议M和S都打开持久化,下面就演示数据是如何丢失的:
- A,B,C三台redis服务器,A是M,B和C是S
- 因为某些原因,A宕机了,它执行自动重启机制,这时候因为关闭了持久化,磁盘里是没有备份数据的,内存里的数据也因为重启丢失了,所以重启之后数据全部丢了
- B和C尝试同步,它们也不管A的数据是不是空,照常同步过来了,所以B和C的数据也丢了
配置
slaveof 192.168.1.1 6379
只需要在S的配置文件里添加上面这一行就可以了,这一行代码的含义是:192.168.1.1 6379是M,我从这儿同步数据进行复制,下面就在我的虚拟机上面实操一下:
配置3台redis,6379是M,6380、6381是S
配置M
[[email protected] redis]# cp redis.conf redis_6379.conf [[email protected] redis]# vi redis_6379.conf bind 192.168.56.10 #修改ip为本机
配置S
[[email protected] redis]# cp redis_6379.conf redis_6380.conf [[email protected] redis]# vi redis_6380.conf #修改端口号和pid文件名 port 6380 pidfile /var/run/redis_6380.pid slaveof 192.168.56.10 6379 #设定复制 #同样拷贝一份配置按照上面的步骤进行修改 [[email protected] redis]# cp redis_6380.conf redis_6381.conf
启动
[[email protected] redis]# src/redis-server redis_6379.conf [[email protected] redis]# src/redis-server redis_6380.conf [[email protected] redis]# src/redis-server redis_6381.conf
测试复制
[[email protected] redis]# telnet 192.168.56.10 6379 Trying 192.168.56.10... Connected to 192.168.56.10. Escape character is ‘^]‘. set school bistu +OK get school $5 bistu quit +OK Connection closed by foreign host. [[email protected] redis]# telnet 192.168.56.10 6380 Trying 192.168.56.10... Connected to 192.168.56.10. Escape character is ‘^]‘. get school $5 bistu #复制成功 set myname pigfly -READONLY You can‘t write against a read only slave. #注意slave不能写,这是默认配置,如需修改请到配置文件修改read-only项 [[email protected] redis]# telnet 192.168.56.10 6381 Trying 192.168.56.10... Connected to 192.168.56.10. Escape character is ‘^]‘. get school $5 bistu #复制成功
时间: 2024-10-06 09:18:30