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

扯淡:

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

主题:

1,Sharded的实现

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

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

  shardedJedisPool的配置如下:(具体可以参考《spring和redis的整合》

<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"  scope="singleton">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1">
<list>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" />
<constructor-arg name="timeout" value="${redis.timeout}" />
<constructor-arg name="weight" value="1" />
</bean>
</list>
</constructor-arg>
</bean>

注入了两个对象: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<Long, S> nodes; // 构造方法
public Sharded(List<S> shards, Hashing algo, Pattern tagPattern) {
this.algo = algo;
this.tagPattern = tagPattern;
// 初始化方法,建立一个个节点
initialize(shards);
}

initialize方法:

    private void initialize(List<S> shards) {
nodes = new TreeMap<Long, S>(); 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<Long, S> 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<Integer, AwardConfigDO> extentTree = new TreeMap<Integer, AwardConfigDO>();
// 获奖区间划分
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<Integer, String> extentTree = new TreeMap<Integer, String>();
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
}

让我们继续前行

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

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

Sharded实现学习-我们到底能走多远系列(32)的更多相关文章

  1. ArrayBlockingQueue-我们到底能走多远系列(42)

    我们到底能走多远系列(42) 扯淡: 乘着有空,读些juc的源码学习下.后续把juc大致走一边,反正以后肯定要再来. 主题: BlockingQueue 是什么 A java.util.Queue t ...

  2. 服务调用方案(Spring Http Invoker) - 我们到底能走多远系列(40)

    我们到底能走多远系列(40) 扯淡:  判断是否加可以效力于这家公司,一个很好的判断是,接触下这公司工作几年的员工,了解下生活工作状态,这就是你几年后的状态,如果满意就可以考虑加入了. 主题: 场景: ...

  3. html5实现饼图和线图-我们到底能走多远系列(34)

    我们到底能走多远系列(34) 扯淡: 送给各位一段话:     人生是一个不断做加法的过程     从赤条条无牵无挂的来     到学会荣辱羞耻 礼仪规范     再到赚取世间的名声 财富 地位    ...

  4. Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)

    我们到底能走多远系列(33) 扯淡: 各位:    命运就算颠沛流离   命运就算曲折离奇   命运就算恐吓着你做人没趣味   别流泪 心酸 更不应舍弃   ... 主题: Spring源码阅读还在继 ...

  5. 初始化IoC容器(Spring源码阅读)-我们到底能走多远系列(31)

    我们到底能走多远系列(31) 扯淡: 有个问题一直想问:各位你们的工资剩下来会怎么处理?已婚的,我知道工资永远都是不够的.未婚的你们,你们是怎么分配工资的? 毕竟,对自己的收入的分配差不多体现了自己的 ...

  6. 定时任务管理中心(dubbo+spring)-我们到底能走多远系列47

    我们到底能走多远系列47 扯淡: 又是一年新年时,不知道上一年你付出了多少,收获了多少呢?也许你正想着老板会发多少奖金,也许你正想着明年去哪家公司投靠. 这个时间点好好整理一下,思考总结一下,的确是个 ...

  7. ThreadPoolExecutor机制探索-我们到底能走多远系列(41)

    我们到底能走多远系列(41) 扯淡: 这一年过的不匆忙,也颇多感受,成长的路上难免弯路,这个世界上没人关心你有没有变强,只有自己时刻提醒自己,不要忘记最初出发的原因. 其实这个世界上比我们聪明的人无数 ...

  8. Spring mvc源码url路由-我们到底能走多远系列(38)

    我们到底能走多远系列38 扯淡: 马航的事,挺震惊的.还是多多珍惜身边的人吧. 主题: Spring mvc 作为表现层的框架,整个流程是比较好理解的,毕竟我们做web开发的,最早也经常接触的就是一个 ...

  9. node实现http上传文件进度条 -我们到底能走多远系列(37)

    我们到底能走多远系列(37) 扯淡: 又到了一年一度的跳槽季,相信你一定准备好了,每每跳槽,总有好多的路让你选,我们的未来也正是这一个个选择机会组合起来的结果,所以尽可能的找出自己想要的是什么再做决定 ...

随机推荐

  1. BPMX3模拟登录

    实现功能只需要输入一个帐号即可登录系统. 需要实现上面的功能需要: 1.编辑imitate.jsp页面 <%@page import="com.hotent.core.util.Con ...

  2. 使用MediaPlayer播放音频-----之一

    MediaPlayer提供了如下方法来指定装载相应的音频文件: 1.void  setDataSource( String  path):指定装载path路径所代表的文件. 2.void  setDa ...

  3. iOS 登陆的实现四种方式

    iOS 登陆的实现四种方式 一. 网页加载: http://www.cnblogs.com/tekkaman/archive/2013/02/21/2920218.ht ml [iOS登陆的实现] A ...

  4. android webview 漏洞背后的节操

    by superhei 2013/09/06 [注:本文提到的都是我个人的观点,该行为也是私人行为,与任何组织.公司无关.另:水军请自重!] 一.前言   这两天,一个2+年前的android web ...

  5. IT公司100题-4-在二元树中找出和为某一值的所有路径

    问题描述: 输入一个整数和一棵二元树.从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径.打印出和与输入整数相等的所有路径. 例如输入整数30和如下二元树   14 / \ 5 16 / ...

  6. iOS闪烁效果工具 GlitchLabel

    GlitchLabel 用于给文字添加闪烁效果,效果图如下: 开发环境: iOS 7.0+ Swift 2.2 Xcode 7 示例代码:https://www.yuedecaifu.com 1 2 ...

  7. HTML5实战教程———开发一个简单漂亮的登录页面

    最近看过几个基于HTML5开发的移动应用,比如臭名昭著的12036移动客户端就是主要使用HTML5来实现的,虽然还是有点反应迟钝,但已经比较流畅了,相信随着智能手机的配置越来越高性能越来越好,会越来越 ...

  8. sql server日志不能shrink或truncate

    Backup log [dbxxx] with truncate_only sql server 2008之后不支持此操作,需要改为: BACKUP LOG dbxxx TO DISK='NUL:' ...

  9. win10系统输入法用户体验

    因为现在的输入法好多的广告弹窗所以我一直用系统原生的输入法,自从去年升级win10以后一直在用自带的输入法, 1.用户界面设计 win10系统自带的输入法用户界面设计非常扁平化,没有哪些所谓的皮肤啥的 ...

  10. HibernateDaoSupport 源码

    package org.springframework.orm.hibernate3.support; import org.hibernate.HibernateException; import  ...