一、什么是Cluster?
redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上都可以存储不同的内容。
Redis-Cluster采用无中心结构,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
二、为什么要使用Cluster?
- 数据分散存储
Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。
举个栗子,我规定:号码为0-59总共60个小球,小明,小红,小李三个人分别拿0-19、20-39、40-59号码的小球,当你想拿到55号球的时候可以直接快速找到小李去拿到55号球。
- 容错机制-投票
为了防止主节点数据丢失,可以为每个主节点可以准备特点数目的备节点,主节点挂掉从节点可以升级为主节点(哨兵模式) 。
容错机制指的是,如果半数以上master节点与故障节点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作. 故障节点对应的从节点自动升级为主节点 , 如果某个主挂掉,而没有从节点可以使用,那么整个Redis集群进入宕机状态
以上内容参考自:Redis入门到精通(十二),Redis集群的意义(一)
三、开始实验
本实验模拟6台redis服务器,以一主一从为一组,共3组实例实现Cluster集群部署
第1步:确保redis.conf文件的daemonize 属性为yes
第2步:制作6个实例,6379,6380,6381,6389,6390,6391
首先制作一个6379,其他的复制粘贴,并且使用命令全局修改文件内容
mkdir redis_cluster #创建一个文件夹用于存放cluster的日志文件
vi redis6379.conf #创建一个文件
配置基本信息
include /usr/local/test/test-redis/redis.conf
port 6379
pidfile "/var/run/redis_6379.pid"
dbfilename "dump6379.rdb"
dir "/usr/local/test/test-redis/redis_cluster"
logfile "/usr/local/test/test-redis/redis_cluster/redis_err_6379.log"
#打开集群模式
cluster-enabled yes
#设定节点配置文件名
cluster-config-file nodes-6379.conf
#设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000
可以使用如下命令在文件中进行全局内容替换
:%s/6379/6389
第3步:保证6个redis服务都正常启动
redis-server redis6379.conf
redis-server redis6389.conf
redis-server redis6380.conf
redis-server redis6390.conf
redis-server redis6381.conf
redis-server redis6391.conf
第4步:合体,以集群方式启动
必须切换目录到redis/src目录下,然后再运行命令,ip地址不可以使用127.0.0.1
切换目录
cd /usr/local/apps/redis-5.0.4/src/
合体命令
redis-cli --cluster create --cluster-replicas 1 192.168.0.181:6379 192.168.0.181:6380 192.168.0.181:6381 192.168.0.181:6390 192.168.0.181:6391 192.168.0.181:6389
第5步:测试
以集群方式登陆客户端
-c 采用集群策略连接,设置数据会自动切换到相应的写主机
redis-cli -c -p 6379
四、jedis的集群开发
即使连接的不是主机,集群会自动切换主机存储。主机写,从机读。
无中心化主从集群。无论从哪台主机写的数据,其他主机上都能读到数据。
public class JedisClusterTest {
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"));
}
}