博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jedis路由key的算法剥离
阅读量:5163 次
发布时间:2019-06-13

本文共 3398 字,大约阅读时间需要 11 分钟。

在Redis集群中,会有很多个分片,如果此时利用Jedis来操作此Redis集群,那么他会把数据路由到不到的分片上。而且如果动态的往集群中增加分片,也不会影响Jedis的功能。究竟是怎么做到的呢?

由于最近公司要集中迁移redis集群,也就是把旧集群的数据迁移到Redis Cluster中,就需要我们自己来整理数据。刚好我这里有个库存热点数据,我们叫做A吧,这个A在Redis集群中,每个分片上都有数据。比如,Redis集群有4个片,而我总库存量为1000,那么会在4个片上放上Key A,每个A中库存量为250.

新的Redis cluster,为了防止热点库存问题,也就申请了4个cluster,每个cluster相当于之前的一个分片。数据在写入的时候,每个cluster会写一个key A,库存量为250.

现在问题来了,有一些Key,比如说B,在原来的Redis集群中,是利用Jedis路由来导向某一片写入的,假设这里写入的是第3片。如果迁移到新的4个Redis cluster中,势必需要写到第三个Redis Cluster中。因为数据迁移,肯定是第一片redis数据迁移到第一个Cluster,第二片redis数据迁移到第二个Cluster,以此类推。

所以这里需要我们来实现和Jedis一样的路由算法,按照Jedis提供的类,我们实现如下:

首先,定义好ShardNode,继承自Jedis的ShardInfo:

public class ShardNode implements ShardInfo {    public ShardNode(String index, Cluster cluster) {        this.index = index;        this.cluster = cluster;    }    private String index;    private Cluster cluster;    @Override    public int getWeight() {        return 1;    }    @Override    public String getName() {        return null;    }    public Cluster getCluster() {        return cluster;    }    public void setCluster(Cluster cluster) {        this.cluster = cluster;    }    public String getIndex() {        return index;    }    public void setIndex(String index) {        this.index = index;    }}

注意,getName方法里面一定要return null, 这样就会根据配置的分片的数量先后顺序来运算哈希key。具体源码如下(翻看KetamaHashing类的源码):

 

protected void initialize(List
shards) { Charset charset = Charset.forName("utf-8"); String key = null; for(int i = 0; i < shards.size(); ++i) { T shardInfo = (ShardInfo)shards.get(i); if (shardInfo == null) { throw new IllegalArgumentException("shard element #" + i + " is null."); } AtomicReference
wrapper = new AtomicReference(shardInfo); this.originals.add(wrapper); for(int n = 0; n < 160 * shardInfo.getWeight(); ++n) { if (shardInfo.getName() == null) { } else { key = shardInfo.getName() + "*" + shardInfo.getWeight() + n; } this.nodes.put(this.algo.hash(key.getBytes(charset)), wrapper); } } }
 

注意我标黄颜色部分,正式因为shardInfo.getName为null,所以我们的路由算法才能够按照配置的分片顺序进行路由。

然后进行实现即可:

public Cluster getCluster(String key) {        return shard.getCluster();    }

这样我们就可以通过key来获取新的Redis Cluster实例了。通过测试用例结果,我们也可以看出Jedis路由算法和我们所写的路由算法是一致的。

@Test    public void testJedisHash() {        Map
map = new HashMap<>(); map.put("192.168.155.84:6379", "0"); map.put("192.168.155.84:6390", "1"); map.put("192.168.155.85:6379", "2"); map.put("192.168.155.85:6390", "3"); String key; List
list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { key = UUID.randomUUID().toString(); ShardNode cluster = storeJimdbs.getShardNode(key); ShardInfo redisShard = jrc.getShardInfo(key); String shardKey = redisShard.toString().split("/")[0]; if (cluster.getIndex().equals(map.get(shardKey))) { list.add("OK"); } else { System.out.println("NNNNNNNotMatch!!!!!!!"); } } System.out.println(list.size()); }

最后运算出来的结果是1000,也就是说1000个随机key,利用Jedis路由算法操作,利用我们写的路由算法操作,其实是打到相同的分片序号上的。

也就是0号分片对应0号cluster。

转载于:https://www.cnblogs.com/scy251147/p/10492619.html

你可能感兴趣的文章
nginx的缓存设置提高性能
查看>>
C基础--单链表的构造
查看>>
光标定位、模糊查询
查看>>
获取Android控件ListView中被选中的某一列的值
查看>>
UVA 11374 Airport Express 机场快线 Dijistra+路径
查看>>
UIWebView 无缝切换到 WKWebView
查看>>
【python小练】0002
查看>>
【Django】不知道为什么就是想学一下 01
查看>>
C# Single Instance WinForms and Microsoft.VisualBasic.dll
查看>>
Query String模块和http小爬虫和events模块和fs模块和stream模块
查看>>
NOIP前的水题记录
查看>>
python:python之禅
查看>>
isKindOf和isMemberOf的区别
查看>>
深入浅出了解frame和bounds
查看>>
InstallShield 打包时需要注意
查看>>
我和面向对象有个约会
查看>>
转:Android Context的理解
查看>>
指定gpu
查看>>
TestNG Assert 详解
查看>>
【noip2004】 不高兴的津津 - 模拟
查看>>