目录
一、前言
二、Redis sharding集群
1、概念及优劣:
2、数据倾斜问题
3、数据丢失问题
4、应用
三、后话
四、参考
最近在所负责的某些系统上遇到了一些Redis相关的问题,刚好在朋友圈聊到Cluster和Sharding这方面的东西,发现有些地方比较模糊,考虑到之前也整理了关于Sentinel集群模式,趁着有点力气整理一下Sharding的一些相关资料。
Cluster模式后面有时间再补充吧。
单点故障:一般的做法是通过一主N从的哨兵模式实现该分片的自动故障转移,具体的方案原理及搭建请参考我的另外一篇文章:Redis哨兵(Sentinel)模式扩容问题:一般只能通过重启的方法进行扩容,但这种办法在键值对数据迁移方面加大了运维侧的难度,且应用层需要做配置改动去支持新的实例。还有另外一种办法,Redis作者推荐可以使用一种PreSharding的办法,这里暂不做介绍,后面再补充。
另:1、关于缓存系统对于该算法运用的相关论文有兴趣的朋友可以参考哥伦比亚大学网站的资料: http://www.cs.columbia.edu/~asherman/papers/cachePaper.pdf2、关于算法原始论文有兴趣的可以参考普林斯顿大学资料:https://www.cs.princeton.edu/courses/archive/fall09/cos518/papers/chash.pdf
redis.clients
jedis
2.8.0
application.properties
#redis sharding instance config
redis_client_timeout=500
redis_one_host=192.168.32.101
redis_one_port=6379
redis_one_password=123
redis_two_host=192.168.32.102
redis_two_port=6380
redis_two_password=123
RedisConfiguration.java
@Configuration
public class RedisConfiguration {
//redis one host
@Value("${redis_one_host}")
private String redisOneHost;
//redis one port
@Value("${redis_one_port}")
private int redisOnePort;
//redis one password
@Value("${redis_one_password}")
private String redisOnePassword;
//redis two host
@Value("${redis_one_host}")
private String redisTwoHost;
//redis two port
@Value("${redis_one_port}")
private int redisTwoPort;
//redis two password
@Value("${redis_two_password}")
private String redisTwoPassword;
//redis client timeout
@Value("${redis_client_timeout}")
private int redisClientTimeout;
@Bean(name="redisPool")
public ShardedJedisPool createRedisPool() throws Exception {
//设置连接池的相关配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(5);
poolConfig.setMaxIdle(2);
poolConfig.setMaxWaitMillis(5000);
poolConfig.setTestOnBorrow(false);
poolConfig.setTestOnReturn(false);
//设置Redis信息
JedisShardInfo shardInfo1 = new JedisShardInfo(redisOneHost,redisOnePort, redisClientTimeout);
shardInfo1.setPassword(redisOnePassword);
JedisShardInfo shardInfo2 = new JedisShardInfo(redisTwoHost, redisTwoPort, redisClientTimeout);
shardInfo2.setPassword(redisTwoPassword);
//初始化ShardedJedisPool
List infoList = Arrays.asList(shardInfo1, shardInfo2);
ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, infoList);
return jedisPool;
}
public static void main(String[] args){
ShardedJedis shardedJedis = null;
try{
RedisConfiguration redisConfiguration = new RedisConfiguration();
ShardedJedisPool shardedJedisPool = redisConfiguration.createRedisPool();
shardedJedis = shardedJedisPool.getResource();
shardedJedis.set("CSDN", "56");
shardedJedis.set("InfoQ","44");
shardedJedis.set("CNBlog","13");
shardedJedis.set("SegmentFault","22");
Client client1 = shardedJedis.getShard("CSDN").getClient();
Client client2 = shardedJedis.getShard("InfoQ").getClient();
Client client3 = shardedJedis.getShard("CNBlog").getClient();
Client client4 = shardedJedis.getShard("SegmentFault").getClient();
System.out.println("CSDN 位于实例:" + client1.getHost() + "|" + client1.getPort());
System.out.println("InfoQ 位于实例:" + client1.getHost() + "|" + client1.getPort());
System.out.println("CNBlog 位于实例:" + client1.getHost() + "|" + client1.getPort());
System.out.println("SegmentFault 位于实例:" + client1.getHost() + "|" + client1.getPort());
}catch(Exception e){
e.printStackTrace();
}finally {
shardedJedis.close();
}
}
}
运行后打印出来的日志看,这几个值是存放到不同的Redis实例中,但是在客户端使用的时候究竟如何分配到不同的分片具体有Jedis实现的一致性哈希算法所决定的;当然,它所支持的默认算法是64位的MURMUR_HASH算法,另外也支持MD5哈希算法。
"C:\Program Files\Java\jdk1.8.0_102\bin\java"...
CSDN 位于实例:192.168.32.101|6379
InfoQ 位于实例:192.168.32.102|6380
CNBlog 位于实例:192.168.32.101|6379
SegmentFault 位于实例:192.168.32.102|6380