知識問答:
傳統的哨兵集羣方式存在哪些缺陷?
1.redis的哨兵集羣方式,每個節點都保存相同的同步數據,可能會存在冗餘的數據;其次只能允許有一個主的節點;屬於中心化集羣;
Redis Cluster 從3.0開始是Redis官方推出一種去中心化的集羣方式.
採用hash槽分片的將數據存放到多個不同的Redis中,從而可以去減少冗餘的數據.
核心原理:採用hash槽,預先分配16384個卡槽,並且將卡槽分配到具體Redis的節點,通過key進行crc16(key)%16384=卡槽,可以根據卡槽存到具體Redis節點,注意一個卡槽可以存放多個不同的key.只有主的節點纔會分配卡槽,從節點沒有卡槽.
卡槽作用: 決定key存放具體的服務器位置,從而實現均攤存放數據.類似我們的數據庫中具體的分表, 優點:動態實現擴容和縮容;
搭建RedisCluster集羣
1.liunx下安裝好redis
2.在usr文件下創建rediscluster文件夾,並配置6個redis.conf文件
3.修改配置redis.conf文件下面幾點,分別是7000 7001 7002 7003 7004 7005
4.配置好配置文件後,依次啓動6臺redis
5.使用命令搭建rediscluster集羣,分配卡槽命令: /usr/redis/bin/redis-cli --cluster create 192.168.0.106:7000 192.168.0.106:7001 192.168.0.106:7002 192.168.0.106:7003 192.168.0.106:7004 192.168.0.106:7005 --cluster-replicas 1
6.確認完成卡槽分配,集羣搭建
7.連接到redis 7000端口 /usr/redis/bin/redis-cli -h 192.168.0.106 -p 7000
8.使用-c集羣連接模式
9.幫助命令
擴容
1.添加7006 . 7007兩個redis
2.啓動7006 .7007兩個節點
3.連接7000節點 ,查看節點信息
4.使用命令將7006節點加入到rediscluster集羣
/usr/redis/bin/redis-cli --cluster add-node 192.168.0.106:7006 192.168.0.106:7000
5.查看節點信息,發現7006已經加入到集羣,且爲主節點.但是沒有分配卡槽
6.使用命令將7007節點加入rediscluster集羣 ,並從於7006主節點
/usr/redis/bin/redis-cli --cluster add-node 192.168.0.106:7007 192.168.0.106:7000 --cluster-slave --cluster-master-id 447889fb4caaeec881eca8331a4c3caf4220ae49
7.加入成功後開始分配卡槽
/usr/redis/bin/redis-cli --cluster reshard 192.168.0.107:7000
8.繼續分配卡槽操作
9.分配成功後查詢節點信息 ,分配成功
縮容
1.先查看節點信息,使用命令將7006節點卡槽分配給7000節點
/usr/redis/bin/redis-cli --cluster reshard 192.168.0.107:7000 --cluster-from d91287701e9b0103f9f561a19f2d1d62fcc1b9c0 --cluster-to b6075e00fa0f7cefe0a9ec4d0abbbc2391050221 --cluster-slots 4096
2.查看縮容後的節點信息
jedis連接RedisCluster集羣
原理:根據cluster help命令查詢key所在卡槽的位置值 . 再根據命令 cluster nodes查詢節點信息, key在哪個節點,然後連接節點,查詢返回數據
@Component
public class RedisCluster {
private static JedisCluster jedis;
static {
Set<HostAndPort> hostAndPortSet=new HashSet<>();
hostAndPortSet.add(new HostAndPort("192.168.0.107",7000));
hostAndPortSet.add(new HostAndPort("192.168.0.107",7001));
hostAndPortSet.add(new HostAndPort("192.168.0.107",7002));
hostAndPortSet.add(new HostAndPort("192.168.0.107",7003));
hostAndPortSet.add(new HostAndPort("192.168.0.107",7004));
hostAndPortSet.add(new HostAndPort("192.168.0.107",7005));
//jedis連接池配置
JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
//最大空閒連接數 ,默認8個
jedisPoolConfig.setMaxIdle(100);
//最大連接數 ,默認8個
jedisPoolConfig.setMaxTotal(500);
//最小空閒連接數
jedisPoolConfig.setMinIdle(0);
//獲取連接最大等待毫秒數
jedisPoolConfig.setMaxWaitMillis(2000);
//對拿到的connection進行validateObject效驗
jedisPoolConfig.setTestOnBorrow(true);
jedis=new JedisCluster(hostAndPortSet,jedisPoolConfig);
}
//根據key獲取value
public static String getKey(String key){
return jedis.get(key);
}
}