- 如何解决:容量不够,redis如何进行扩容? 并发写操作, redis如何分摊? 另外,主从模式,薪火相传模式,主机宕机,导致ip地址发生变化,应用程序中配置需要修改对应的主机地址、端口等信息
- 之前通过代理主机来解决,但是redis3.0中提供了解决方案,就是无中心化集群配置
- Redis 集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库数据分布存储在这N个节点中,每个节点存储总数据的1/N
- Redis 集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求
主要作用
- Redis集群支持多个Master,每个Master又可以挂载多个Slave
- 由于集群Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
- 客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个可用节点即可
- 槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系
如何配置
- 修改配置文件,复制多个redis
cluster-enabled yes 打开集群模式
cluster-config-file nodes-6379.conf 设定节点配置文件名
cluster-node-timeout 15000 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换
include /home/bigdata/redis.conf
port 6379
pidfile "/var/run/redis_6379.pid"
dbfilename "dump6379.rdb"
dir "/home/bigdata/redis_cluster"
logfile "/home/bigdata/redis_cluster/redis_err_6379.log"
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
-
将redis启动后,配置集群
replicas 1 采用最简单的方式配置集群,一台主机,一台从机,正好三组
redis-cli --cluster create --cluster-replicas 1
192.168.11.101:6379
192.168.11.101:6380
192.168.11.101:6381
192.168.11.101:6389
192.168.11.101:6390
192.168.11.101:6391 -
集群策略连接,-c参数设置数据会自动切换到相应的写主机

查看集群信息
cluster nodes
集群节点分配
- 一个集群至少要有三个主节点
- 选项 --cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点
- 分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上
slots插槽
- 一个 Redis 集群包含 16384 个插槽(hash slot)
- 数据库中的每个键属于这 16384 个插槽的其中一个分片,简言之,集群中的每个Redis实例都被认为是整个数据的一个分片
- 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和
问题:CRC16算法产生的hash值有16bit,该算法可以产生2^16=65536个值。换句话说值是分布在0~65535之间,有更大的65536不用为什么只用16384就够?
(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为16384时,这块的大小是: 16384÷8÷1024=2kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。
(2)redis的集群主节点数量基本不可能超过1000个。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
(3)槽位越小,节点少的情况下,压缩比高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。
- 集群中的每个节点负责处理一部分插槽,假设集群中有3个节点:

- 好处:方便扩缩容和数据分派查找
在集群中录入值
- 每次录入、查询键值,redis都会计算出该key应该送往的插槽,如果不是该客户端对应服务器的插槽,redis会报错,并告知应前往的redis实例地址和端口
- 不在一个slot下的键值,是不能使用mget,mset等多键操作
- 可以通过{}来定义组的概念,从而使key中{}内相同组内容的键值对放到一个slot中去

查询集群中的值
CLUSTER GETKEYSINSLOT <slot><count>

故障恢复
- 主节点宕机,超时15秒,从节点自动变为主节点;主节点恢复后,变成从节点
- 配置文件参数cluster-require-full-coverage
- yes:如果某一段插槽的主从都挂掉,那么整个集群都挂掉
- no:如果某一段插槽的主从都挂掉,那么该插槽数据全都不能使用,也无法存储
集群的Jedis
java
public static void main(String[] args) {
Set<HostAndPort>set =new HashSet<HostAndPort>();
set.add(new HostAndPort("192.168.31.211",6379));
JedisCluster jedisCluster=new JedisCluster(set);
jedisCluster.set("k1", "v1");
System.out.println(jedisCluster.get("k1"));
}
集群好处
- 实现扩容
- 分摊压力
- 无中心配置,相对简单
集群不足
- 多键操作是不被支持的
- 多键的Redis事务是不被支持的
- lua脚本不被支持