Sharded实现学习-我们到底能走多远系列(32)
发布日期:2021-08-31 16:58:41 浏览次数:9 分类:技术文章

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

我们到底能走多远系列(32)

扯淡:

  工作是容易的赚钱是困难的

  恋爱是容易的成家是困难的
  相爱是容易的相处是困难的
  决定是容易的可是等待是困难的

 

主题:

1,Sharded的实现

 
 ShardedJedis是基于一致性哈希算法实现的分布式Redis集群客户端。
 
 关于一致性哈希算法 可以参考
 

  Memcached 和 redis 都使用了该算法来实现自己的多服务器均匀分派存储值的。

 

  shardedJedisPool的配置如下:(具体可以参考)

 

 

 注入了两个对象:jedisPoolConfig 和 JedisShardInfo

然后产生ShardedJedis:

public ShardedJedis getRedisClient() {        try {            ShardedJedis shardJedis = shardedJedisPool.getResource();            return shardJedis;        } catch (Exception e) {            log.error("getRedisClent error", e);        }        return null;    }

ShardedJedis 继承 BinaryShardedJedis 继承 Sharded<Jedis, JedisShardInfo>

 

Sharded的实现就是前面一致性哈希算法的实现啦~

// 使用TreeMap来完成构造出一个很多节点的环形private TreeMap
nodes;// 构造方法public Sharded(List
shards, Hashing algo, Pattern tagPattern) { this.algo = algo; this.tagPattern = tagPattern; // 初始化方法,建立一个个节点 initialize(shards);}

initialize方法:

 

private void initialize(List shards) {        nodes = new TreeMap
(); for (int i = 0; i != shards.size(); ++i) { final S shardInfo = shards.get(i); if (shardInfo.getName() == null) for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo); } else // 将设置的权重放大160倍,产生更多的节点,因为hash一下就散落到各道各处了,如此就是所谓的虚拟节点,以保证均匀分布 for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo); } resources.put(shardInfo, shardInfo.createResource()); } }

 

redis放key value的时候,需要判断应该放在那个服务器上,就是判断hash后更靠近哪个节点。

public R getShard(byte[] key) {        return resources.get(getShardInfo(key));    }    public R getShard(String key) {        return resources.get(getShardInfo(key));    }    //最终调用方法    public S getShardInfo(byte[] key) {       // 首先判断是不是tree中最大的key,及最后一个,注意我们是环,所以最大的后面就要从头开始。        SortedMap
tail = nodes.tailMap(algo.hash(key)); // 是最后一个key了,所以取第一个节点对应的服务器 if (tail.size() == 0) { return nodes.get(nodes.firstKey()); } // 不是最后一个就是比自己离自己最近的大的key对应的服务器 return tail.get(tail.firstKey()); } public S getShardInfo(String key) { return getShardInfo(SafeEncoder.encode(getKeyTag(key))); }

 

到这里基本明白了如何抽象实现一个环状的排序的数据结构了。值得借鉴。

 

2,实践中的一个例子

 问题:模拟一个抽奖的效果,随机产生一个范围内的数字,看是否在中奖的区域内来判断是否中奖。 中奖区域分多个层次的奖项。
如图:
 
|0 -------奖项1--------200|201-------奖项2--------1000|1001-------奖项3-------5000|5001-------没奖---------100000|
 
使用了TreeMap来实现
从项目里拉出来的代码:
TreeMap
extentTree = new TreeMap
(); // 获奖区间划分 for (AwardConfigDO awardConfig : configList) { //Probability是区间节点,如100,500 extentTree.put(awardConfig.getProbability(), awardConfig); } // 进入中奖区 random 是随机产生的数字,首先判断是否进入中奖区 if (random < extentTree.lastKey()) { //然后判断 中奖奖项 是哪个 AwardConfigDO awardConfig = extentTree.higherEntry(random).getValue(); }

 

所以TreeMap可以来抽象实现这种区间的结构。关于TreeMap可以看API哦。

 

--------------------20130827补充-----------------------

需要注意的是 使用了TreeMap 需要考虑key相同的情况,这种情况就需要接受前一个映射关系会被替换的情况。

public static void main(String[] args) {        TreeMap
extentTree = new TreeMap
(); extentTree.put(1, "1"); extentTree.put(10, "2"); extentTree.put(10, "3"); extentTree.put(100, "4"); String value = extentTree.higherEntry(5).getValue(); System.out.println(value);//output:3 }

 

 

 

让我们继续前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不会成功。

共勉。

 

转载地址:https://blog.csdn.net/weixin_34082789/article/details/85581104 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:poj 3498(最大流+拆点)
下一篇:ios 手势识别

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月10日 08时31分07秒