redis集群去中心化

转载一篇博客
原地址node

1 Redis传统集群和分片集群web

Redis传统集群都是基于主从复制+哨兵模式实现的,采用不一样的主从复制策略(如一主多从、树状主从)搭建Redis集群实现高可用,使用哨兵模式来进行Redis主机宕机以后的投票选举,实现自动化故障发现和转移,从而更好地保护Redis集群,最大化保证集群高可用。redis

在传统Redis集群模式中,也存在一些问题:算法

  1. 通常都是使用一主多从或者树状主从的方式来搭建Redis集群的,始终只有一个Redis主机来接收和处理写请求,而且Redis主机和从机数据始终是保持彻底同步的,随着业务复杂度升级,若是从机比较多的状况下,因为每一个Redis从机自己的持久化机制,再加上Redis主机定时的数据同步,数据同步效率必然会下降,而且从机和主机数据始终是同步的,存在大量冗余数据,浪费内存空间,从而会对运行的Redis集群中的每一个Redis服务器运行性能形成影响。

(2) 根据主从复制的读写分离原则,主机只能负责写操做,传统Redis集群只有一个主机,若是是高并发请求的状况下,那么就会致使这个Redis主机写操做的压力很是大,同时还会加剧同步数据到从机的负荷,而且Key也不能分摊到其余Redis主机,一旦出现缓存雪崩问题就会致使大量Key同时失效,丢失不少重要的数据。缓存

传统Redis集群任什么时候候都要保证至少有一个Redis主机在正常运行(除了Redis主机宕机后,哨兵模式正在投票选举的状况以外,由于投票选举结束以前,谁也不知道主机和从机是谁,此时Redis也会开启保护机制,禁止写操做,直到选举出了新的Redis主机),是一种中心化的集群实现方案,每一个从机和主机的耦合度很高。服务器

 

Redis分片集群对Redis集群进行分片,采用多主多从的方式实现Redis集群,每个分片都是由一个Redis主机和多个从机组成,片区和片区之间是相互平行的,Redis Cluster就是Redis 3.0+版本以后官方推荐的一种分片集群实现方式,主要是基于Hash卡槽(slot)和crc16(key)算法的实现策略来实现Redis集群分片和数据跨主机转移、共享。这是一种去中心化的集群解决方案,能够实现Redis动态扩容和缩容,可是缺点就是集群环境比较复杂,搭建成本高并发

 

2 Redis Cluster去中心化分片集群

Redis 3.0+版本开始官方推出了去中心化分片集群Redis Cluster,原理采用hash槽的概念预先分配16384个卡槽而且将该卡槽分配给提供具体服务的Redis片区节点用来存放每一个Redis主机对应卡槽范围的数据svg

须要注意的是:高并发

(1) hash卡槽只会分配给每一个片区的主机,从机不会分配卡槽性能

(2) 每一个hash卡槽能够存放多个Key

(3) hash卡槽的目的是确认数据存放到哪一个片区的Redis主机,实现Redis集群分摊Key,减小缓存雪崩致使数据丢失带来的意外风险。

(4) 每一个片区的Redis主机卡槽数都对应一个范围,多个片区之间卡槽数范围是等比分配的(1:1,好比存在3个片区对应3个Redis主机,那么3个Redis主机的卡槽总数分别是:16384/3。3个Redis主机的卡槽范围分别是:

第一台Redis主机:0~5460

第二台Redis主机:5461~10921

第三台Redis主机:10922~16383

 

(5) 对于每次读写操做的的Key值都会计算对应的卡槽数,根据计算出的卡槽数会把Key存入到卡槽区间范围包含这个卡槽数的Redis主机中,或者从包含这个Key卡槽数的卡槽范围的Redis主机中获取Key。

 

(6) Key的卡槽数计算是基于crc16算法实现的,根据每次写入/读取的Key的值不一样,该算法会计算出不一样的卡槽数,Key的卡槽数计算公式:

N(Key的卡槽数)=crc16(Key)%16384

若是写入的Key计算出的卡槽数不在当前操做的Redis主机的卡槽数范围内,那么会自动把这个Key转发到卡槽范围包含这个Key的卡槽数的Redis主机中进行写操做。

同理,若是须要获取的Key计算出的卡槽数也不在当前操做的Redis主机卡槽范围内(当前操做的Redis主机中没有这个Key),那么也会自动转发到包含这个Key的卡槽数的卡槽范围的Redis主机中去获取到这个Key。

 

Redis Cluster去中心化分片集群使用Hash卡槽来肯定和定位Key的读写位置,最大的优势是有利于Redis动态扩容、缩容把缓存雪崩数据丢失的风险降到最小。

 

3 Redis Cluster去中心化分片集群环境搭建

搭建思路:在考虑到服务器资源的状况下,可使用单机版服务器经过端口区分不一样的Redis节点,搭建Redis伪集群。

Redis伪集群指的是:在一台服务器上实现Redis集群,使用不一样的Redis配置文件启动不一样的Redis服务,使用端口区分不一样的Redis服务

 

  1. 批量复制redis解压目录

mkdir rediscluster

cd rediscluster/

mkdir redis7000

mkdir redis7001

mkdir redis7002

mkdir redis7003

mkdir redis7004

mkdir redis7005

 

 

  1. 修改每一个Redis目录下的redis.conf配置文件

 

daemonize yes #设置后台启动

# bind 127.0.0.1 ##注释绑定的本机ip

protected-mode no ; ## 设置容许外部访问

port 7005 #修改端口号,从7000到7005(经过不一样端口号区分不一样Redis服务)

 

Redis Cluster去中心化分片集群相关配置:

cluster-enabled yes #开启cluster,去掉注释

cluster-config-file 7000nodes.conf #自动生成(端口号+nodes.conf,不能重复)

cluster-node-timeout 15000 #节点通讯时间

logfile   /usr/rediscluster/redis7005/redis.log (日志目录,三级目录尽可能不要重复,区分不一样端口运行的Redis服务的日志文件)

 

 

  1. 经过指定不一样的redis.conf配置文件,分别启动每一个端口的redis服务

 

/usr/redis/bin/redis-server /usr/rediscluster/redis7000/redis.conf

/usr/redis/bin/redis-server /usr/rediscluster/redis7001/redis.conf

/usr/redis/bin/redis-server /usr/rediscluster/redis7002/redis.conf

/usr/redis/bin/redis-server /usr/rediscluster/redis7003/redis.conf

/usr/redis/bin/redis-server /usr/rediscluster/redis7004/redis.conf

/usr/redis/bin/redis-server /usr/rediscluster/redis7005/redis.conf

  1. 链接一个redis客户端,测试数据写入

/usr/redis/bin/redis-cli -h 127.0.0.1 -p 7000

注意:提示以下异常表示没有使用Redis Cluster命令分配Hash卡槽,须要先使用Redis Cluster官方命令分配卡槽(Redis 5.0+版本以上,低版本不兼容,须要自行安装低版本的Hash卡槽分配插件,建议使用Redis 5.0+版本)

 

(error) CLUSTERDOWN Hash slot not served  说明没有分配hash槽

 

解决方案:使用Redis Cluster命令分配Hash卡槽(默认分配16384个):

/usr/redis/bin/redis-cli --cluster create  127.0.0.1:7000  127.0.0.1:7001  127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005  --cluster-replicas 1

cluster-replicas 1 表示等比分配Hash卡槽和从机到每个Redis主机

7000 Master 【0~5460 Hash slot(5461)】 - 7003 Slave
7001 Master 5461~10921 Hash slot(5461) - 7004 Slave
7002 Master 【10922~16383 Hash slot(5461)- 7005 Slave

 

注意:在使用命令进行Redis Cluster去中心化分片集群初始化的时候,建议最好使用真实服务器的ip地址搭建,不然若是客户端访问某个Redis主机的时候,若是指定的Key在这个Redis主机中不存在,那么根据Hash卡槽机制,会自动在服务器进行Redis主机转发和重定向,直到获取到Key。这样会致使客户端链接的Redis服务器ip地址全都变成127.0.0.1,再次链接就会失败。

 

执行Redis Cluster集群初始化命令的时候,会提示分配Redis Cluster去中心化分片集群中的主机、主机对应的卡槽、主机关联的从机:

M表示是Master主机,slots表示每一个Redis主机分配的Hash卡槽范围

S表示是Slave从机,replicates 后面的id表示从机对应的主机id

Redis Cluster去中心化分片集群和环境搭建比手动配置主从复制实现传统Redis集群更加方便灵活,可是这种基于Redis Cluster命令的方式实现Redis Cluster仅限于Redis 5.0+版本以上,低版本Redis实现Hash卡槽分配仍是比较复杂的,须要本身安装第三方插件实现。

 

再次运行,链接Redis客户端,发现仍是报错

/usr/redis/bin/redis-cli -h 127.0.0.1 -p 7000

错误缘由:须要使用Redis Cluster方式链接Redis服务器

 

解决方案:加入-c扩展参数,表示链接到Redis Cluster去中心化分片集群服务

/usr/redis/bin/redis-cli -h 127.0.0.1 -p 7000 –c

/usr/redis/bin/redis-cli --cluster help

 

 

转载请注明原做者