1.为了达到redis数据库的高可用,所以需要在单机的基础上建立集群,有以下几种集群模式:
1、主从复制
2、哨兵模式
3、Redis官方提供的Cluster集群模式(服务端)
4、Jedis sharding集群(客户端sharding)
5、利用中间件代理,比如豌豆荚的codis等
主从复制
1.主从环境搭建:
如要把ip地址为192.168.17.102的redis机器加入到ip地址为192.168.17.101的机器作为从服务器,可以通过下面方式:
- 1.ip地址为192.168.17.102的机器的Redis配置文件增加slaveof 192.168.17.101 6379,重启102的redis服务
- 2.ip地址为192.168.17.102的机器上的redis服务执行slaveof 192.168.17.101 6379
可以通过info replication命令查看各自的状态。
主从复制原理:
- 从服务器连接主服务器,发送SYNC命令;
- 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
- 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
- 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
- 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;(从服务器初始化完成)
- 主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令(从服务器初始化完成后的操作)
优点:
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
- Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。
- Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据
缺点:
- Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
- 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
- Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
哨兵模式
哨兵模式英文名Sentinel,它是为了解决Redis集群的高可用应运而生的。Redis集群,一般来说只会有一个master服务,当master挂掉之后,之能手动切换master就会造成一段时间内的服务不可用。sentinel就是专门针对这种情况而产生的一个监听服务。它主要负责监听我们一个组内所有Redis,当我们的master挂掉之后,它就会根据Raft算法进行选举一台新的leader出来,然后将选举出来的leader当成我们的master。
1.哨兵模式搭建:
哨兵模式的主要作用就是监控弄Redis集群,所以我们搭建哨兵模式之前要确认我们的Redis集群已经成功搭建了。一般每个redis服务器都会搭建一个哨兵服务器,哨兵模式的搭建其实也相对比较简单,只需要配置主节点监控即可。
# 找到redis根目录下面的sentinel.conf的配置文件,修改如下配置
daemonize yes
port 26379
protected-mode no
dir /usr/local/redis/redis-5.0.1/sentinel-tmp
sentinel monitor mymaster 192.168.222.135 6379 2
sentinel auth-pass mymaster 48835a9c-7a5a-4ec8-af6a-80af3e87b194
# 如果哨兵3s内没有收到主节点的心跳,哨兵就认为主节点宕机了,默认是30秒
sentinel down-after-milliseconds mymaster 3000
# 如果10秒后,master仍没活过来,则启动failover,默认180s
sentinel failover-timeout mymaster 10000
启动时先启动Redis服务,然后在启动sentinel服务:
# 启动redis服务
redis-server redis.conf
# 启动sentinel
redis-sentinel sentinel.conf
2.哨兵功能:
- 1.监控主服务器和从服务器是否正常运行。
- 2.主服务器出现故障时自动将从服务器转换为主服务器。
3.工作原理:
- 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
- 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)
- 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
- 当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
- 在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
- 若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。
- 当主服务器被判定为客观下线之后,各个哨兵服务器将会选举出一个领头哨兵,有这个领头哨兵对下线服务器进行故障转移操作
4.领头Sentinel
故障转移开始时,只需要一个Sentinel来执行这个工作。所以对于Sentinel集群,就需要选举一个领头Sentinel来做这个事。
选举流程:
- 每一个Sentinel都有选举权和被选举权,并且在一轮选举中只有一次机会。
- 每个发现master宕机的Sentinel会发送命令给其他Sentinel,希望把自己设置为局部领头Sentinel。设置局部领头Sentinel规则为先导先得,Sentinel会把最先收到命令中的runId设为自己的局部领头Sentinel;并返回消息。
- 收到返回消息并解析,判断自己是否已被设置为局部领头Sentinel。
- 当一个Sentinel被超过一半Sentinel服务设局部领头Sentinel,则认定该Sentinel为领头Sentinel服务。
- 如果没有选举出来,则开始重新一轮选举。
5.数据丢失
1).异步复制导致数据丢失:
主从服务之间的数据复制是异步进行的,当有一部分命令在写入到主服务后,主服务宕机没来及命令传播到从服务器,那么会丢失这部分命令。
2).脑裂
当master服务脱离了正常网络被认定为宕机,切换新的master,出现了俩个master,即为所谓的脑裂。但是client还没来及切换master,继续会写入数据,当旧的重新上线后被改为从服务,会清空旧的master服务数据去复制新的master,那么会丢失一部分数据。
优点:
- 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
- 主从可以自动切换,系统更健壮,可用性更高。
缺点:
- 在Sentinel模式在进行主备切换时,有可能会出数据丢失情况。
- Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
Cluster集群
redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。
Redis-Cluster采用无中心结构,它的特点如下:
- 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
- 节点的fail是通过集群中超过半数的节点检测失效时才生效。
- 客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
工作方式:
在redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点A1都宕机了,那么该集群就无法再提供服务了。
Jedis sharding集群
Redis Sharding可以说是在Redis cluster出来之前业界普遍的采用方式,其主要思想是采用一致性hash算法将存储数据的key进行hash散列,这样特定的key会被定为到特定的节点上。
Jedis的Redis Sharding实现具有如下特点:
- 采用一致性哈希算法,将key和节点name同时hashing,然后进行映射匹配,采用的算法是MURMUR_HASH。采用一致性哈希而不是采用简单类似哈希求模映射的主要原因是当增加或减少节点时,不会产生由于重新匹配造成的rehashing。一致性哈希只影响相邻节点key分配,影响量小。
- 为了避免一致性哈希只影响相邻节点造成节点分配压力,ShardedJedis会对每个Redis节点根据名字(没有,Jedis会赋予缺省名字)会虚拟化出160个虚拟节点进行散列。根据权重weight,也可虚拟化出160倍数的虚拟节点。用虚拟节点做映射匹配,可以在增加或减少Redis节点时,key在各Redis节点移动再分配更均匀,而不是只有相邻节点受影响。
- ShardedJedis支持keyTagPattern模式,即抽取key的一部分keyTag做sharding,这样通过合理命名key,可以将一组相关联的key放入同一个Redis节点,这在避免跨节点访问相关数据时很重要。
当然,Redis Sharding这种轻量灵活方式必然在集群其它能力方面做出妥协。比如扩容,当想要增加Redis节点时,尽管采用一致性哈希,毕竟还是会有key匹配不到而丢失,这时需要键值迁移。
作为轻量级客户端sharding,处理Redis键值迁移是不现实的,这就要求应用层面允许Redis中数据丢失或从后端数据库重新加载数据。
利用中间件代理
中间件的作用是将我们需要存入redis中的数据的key通过一套算法计算得出一个值。然后根据这个值找到对应的redis节点,将这些数据存在这个redis的节点中。
常用的中间件有这几种:Twemproxy、Codis、nginx