什么是主从同步
主从分布是部署多个redis实例,一主多从,当主实例挂了,那么我们就可以用从实例替换上去,增加了系统的稳定性。
CAP理论
C:一致性:分布式的系统中同一时刻有一样的值。
A:可用性:集群故障之后依旧可以相应客户端的读写请求。
P:分区容错性:系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
而分布式系统往往分布在不同的机器上面。这意味着必然有网络断开的风险,这个网络断开的场景的专业词汇叫网络分区。
当网络之间无法通信时,节点数据不在统一,那么一致性不满足了,或者我们暂停服务,那么可用性不满足了。
也就是说当网络分区时,一致性和可用性无法2全。
redis的最终一致性
redis的主从数据是异步同步的,所以redis系统不满足一致性要求。redis的主节点修改数据后,立即返回,因此就算主从网络断开,主节点依旧可以提供服务。满足可用性,当网络恢复了,从节点会尽可能的同步数据。
增量同步
这个同步方式是主节点会把对自己状态修改的指令记录在内存buffer中,redis的复制内存buffer是一个定长的环形数组,如果数组满了,将会覆盖这个数组。因此如果长时间无法同步,那么指令可能会被覆盖。
快照同步
需要将主库的数据全部快照到磁盘文件,然后将快照文件传给子节点。从节点立即进行一次全量加载,加载之前需要将数据清空,加载后,在进行增量同步。(个人理解是和持久化一样的策略,进行快照时,新的操作用增量),但是存在一种情况,就是在快照和同步的时候,增量缓存已经被覆盖,那么只增在进行快照,然后buffer又被覆盖,进入了死循环。因此buffer大小必须设置好。
无盘复制
快照时会很严重的io操作,对系统很大的影响,我们可以通过服务器直接将套接字将快照内容发到从节点,生成快照是一个遍历的过程,主节点一遍遍历内存一遍序列化内容发送到从节点,从节点接受后也是先缓存到磁盘,然后加载到从节点里面。
我们可以用wait指令强行同步复制。wait 1 1,1就是一个从库,0就是最多等待时间。如果时间=0,那么将将无限制一致等待。
sentinel 自动化切换
前面介绍了主从同步的策略实现以及原理。但是主节点出现故障,还是要手动去切换到从节点,为了避免这个问题,redis官方提供了一个方案-redis sentinel 来处理。可以在主节点挂了之后自动切换到从节点。
我们一般用3~5个sentinel作为集群,来监察redis的集群。客户端访问redis集群的时候,一般先去访问sentinel,从其中获取主节点地址,然后再去访问redis,当redis主节点挂了之后,客户端访问失败后,再次访问sentinel,他会选一个最优的从节点作为主节点,并把地址返回给客户端。而sentinel会持续监控这个坏掉的主节点,等其回复了之后将其作为从节点。
主节点断掉了,那么以为消息的丢失,因为redis的消息同和和zookeeper不一样是异步,如果延迟过大,可能造成很大的影响。
min-slaves-to-write 1
min-slaves-max-lag 10
Sentinel 采用上面的命令来尽量减少丢失,第一个参数是,起码必须有1个正在正常复制中,第二个参数是如果超过10秒没有复制,那么就是不正常复制了。
codis 方案
大数据量下单个redis实例是明显不够的,原因如下:
1.导致内存过大,这样主从复制的时候全量同步时间过长,其次持久化时间也太长,重启消耗大量时间资源。
2.云环境下,单个实例内存是收到限制的。
3.redis是基于多路io复用的单线程,对cpu利用率不高。
因此redis集群应运而生,多个redis实例可以有效提高cpu使用率,而codis是一个非常好的方案,它是一个代理中间件和redis一样使用redis的协议来对外提供服务。当客户端向codis发送指令时,codis负责将指令转发到后面的redis实例完成,起到一个负载均衡,代理的作用。codis上连接的所有redis实例构成了一个集群。codis对客户端是透明的,客户端就像直接使用redis实例一样。codis是无状态的,我们可以同时启动多个实例,来增加其容错性,以及提高并发量。
那么问题来了,一个key到底对应哪个redis实例呢?
codis这样玩的,他对每个key做一个运算,然后对1024取模得到一个值,codis在内存维护的一个映射关系。就是redis实例和1024的对应关系,然后这个值通过这个映射关系,找打对应的redis实例。
那么问题又来了,我们如何对codis同步数据,同步映射关系,这边采用的是使用zookeeper来持久化映射关系,同时codis提供了一个dashboard来观察修改槽位关系,当槽位关系变化时,codis会监听到变化,从而同步其关系。
缺点:key分布式了,所以不再支持事务,其次是动态扩容时,key的迁移消耗资源太大。
cluster(亲儿子)
cluster是redis官方推出的方案,采用去中心化的方案来集群,多个节点通过一个二进制协议交换集群信息。redis将数据的key分为16384 的 slots,其槽点的信息存在每一个节点里面,当客户端获取数据时,先获取到整个槽点的信息,且将其缓存下来。RedisCluster 的每个节点会将集群的配置信息持久化到配置文件中,所以必须确保配置文件是可写的,而且尽量不要依靠人工修改配置文件。具体配置看详细即可。欧了