官方文档
Redis cluster tutorial – Redis 官方基础教程,了解基本概念、创建使用
Redis Cluster Specification – Redis Redis 聚类中的核心算法
解决问题
- Redis 容量不够需要扩容
- 扩容后需要解决并发写操作
- 主从模式时,主机宕机,从机变化
集群
最开始一般通过代理主机来解决,Redis 3.0 版本提供了无中心化集群配置。
Redis 集群实现了对 Redis 的水平扩容,即启动 N 个 redis 节点,将整个数据库分布存储在这 N 个节点中,每个节点存储总数据的 1/N。
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
本地尝试集群
步骤一:生成一个端口的配置文件
include <基本配置文件绝对路径>
daemonize yes
port <port>
pidfile <pidfile>
dbfilename <dbfilename>
dir <dir>
appendonly no # 或者更换AOF的名字
logfile <logfile>
cluster-enabled yes
cluster-config-file <config file>
cluster-node-timeout <timeout>例如,生成 6380 端口的配置文件 redis6380.conf。
include /home/bigdata/redis.conf
port 6380
pidfile "/var/run/redis_6380.pid"
dbfilename "dump6380.rdb"
dir "/home/bigdata/redis_cluster"
appendonly no
logfile "/home/bigdata/redis_cluster/redis_err_6380.log"
cluster-enabled yes
cluster-config-file nodes-6380.conf
cluster-node-timeout 15000步骤二:使用 cp 和 vim 的替换操作再生成 5 个端口的配置文件
cp redis6380.conf redis6381.conf 命令来生成 6381 至 6385 端口的配置文件
vim redis6381.conf 打开文件
%s/6380/6381 将文件中 6380 替换成 6381.
:wq 保存并退出文件
其余端口同理
步骤三:启动 6 个 Redis 服务
redis-server redis6380.conf,其余端口同理。
步骤四:检查集群文件生成
使用 ll 命令查看当前文件夹是否生成了集群配置文件 node-*.conf*。
如果没有,ps -ef|grep redis 命令查看 PID,杀死进程并重新启动。
(没生成的去 bin 目录看看?Or 每生产的要关闭哨兵)
步骤五:将 Redis 服务合体
cd <redis_path>/src 更新到 redis 安装目录的 src 文件夹下。
redis-cli --cluster create --cluster-replicas 1 <IP1:port1> <IP2:port2> <IP3:port3> <IP4:port4> <IP5:port5> <IP6:port6> 使用命令进行配置集群。
此处不要使用本地 IP 地址 127.0.0.1,而是使用真实 IP 地址 OR 根据配置文件中 bind 判断?
--cluster-replicas 1 中 1 代表从机的数量。
有密码的,要加上 -a <password>。
步骤六:redis-cli 登录
redis-cli -c -p 6380 命令来登录。
不设置 -c 可能能直接进入读主机,存储数据时,会提示 (error) MOVED 12706 <IP:port> 重定向。
-c 采用集群策略连接,设置数据会自动切换到相应的写主机。
127.0.0.1:6380>cluster nodes 登陆后,查看集群信息。
运行机制
Redis 集群如何分配节点
一个集群至少要有三个主节点。
选项 --cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
分配原则尽量保证每个主数据库运行在不同的 IP 地址,每个从库和主库不在一个 IP 地址上。
Slots 概念
一个 Redis 集群包含 16384 个插槽 (hash slot),数据库中的每个键都属于这 16384 个插槽的其中一个。
集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽,其中 CRC16 (key) 语句用于计算键 key 的 CRC16 校验和。
集群中的每个节点负责处理一部分插槽。例如:节点 A 负责处理 0 号至 5460 号插槽,节点 B 负责处理 5461 号至 10922 号插槽,节点 C 负责处理 10923 号至 16383 号插槽。
集群中录入值
当节点 A 传入一个值对应 9000 号插槽时,redis 会提示错误并将该处理转移到节点 B 中。
不在一个 slot 下的键值对是不可以使用 mget、mset 等多建操作,会提示 ... dont hash to the same slot。
可以通过 {} 来定义组的概念,从而使 key 中 {} 内相同内容的键值对放到一个 slot 中去,例如 mset k1{groupA} v1 k2{groupA} v2 k3{groupA} v3 来将 k1 、 k2 和 k3 定义到一个组中。
其他命令
CLUSTER keyslot <key> 获取对应的插槽值
CLUSTER countkeysinslot <slot> 获得 slot 插槽中值的个数,但是只能看到当前节点包含的插槽;不包含的插槽无法查看内容,返回 0.
CLUSTER GETKEYSINSLOT <slot><count> 返回 count 个 slot 槽中的键。
故障恢复
如果主节点下线?从节点能否自动升为主节点?注意:15 秒超时
主节点恢复后,主从关系会如何?主节点回来变成从机。
如果某一段插槽的主从都挂掉,而 cluster-require-full-coverage 为 yes ,那么,整个集群都挂掉;为 no ,那么,该插槽数据全都不能使用,也无法存储。
集群的 Jedis 开发
public class JedisClusterTest {
public static void main(String[] args) {
HostAndPort hostAndPort = new HostAndPort("192.168.31.211",6379);
JedisCluster jedisCluster=new JedisCluster(hostAndPort);
// 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"));
}
}