源码走读-从JedisCluster的设计来发现对象池的奥秘

JedisCluster究竟是如何获得一个connection的?内部对象池又是如何工作的?

今天我们就去JedisCluster的源码看看,一探究竟。

好,先从JedisCluster开始。

JedisCluster

可以看到JedisCluster中除了构造函数之外,就是各种命令。建立连接是从构造函数开始,而JedisCluster作为一个子类一般是不会去直接去负责连接这件事情的,而是交给父类。所以我们去父类BinaryJedisCluster看看。

BinaryJedisCluster

可以发现,BinaryJedisCluster也没有去管新建连接这件事,而是交给了一个叫JedisClusterConnectionHandler的连接处理器去完成“连接”这件事情。

JedisClusterConnectionHandler

可以看到JedisClusterConnectionHandler把初始化连接的事交给了JedisClusterCache。

我们看到在构造函数的最后一个方法是initialSlotsCache。此方法负责把槽和传入的master节点初始化。就是用两个循环来完成初始化。现在我们去看看JedisClusterInfoCache。

JedisClusterInfoCache

通过上面的源码,我知道了传入的master列表最终被put进入了一个hashmap。key是"ip:port",value则是一个JedisPool。

接下来就看看JedisPool的实现吧。

JedisPool

我们发现,JedisPool并没有自己去实现对象池,而是直接使用了GenericObjectPool。而且是著名的apache commons包里的pool2。

现在去父类看看。

JedisPoolAbstract

Pool<Jedis>

可以发现此处使用了apache的pool2来实现的Jedis对象池。

好,现在就去看看GenericObjectPool的实现吧。

GenericObjectPool

在整个的构造函数里,我们只发现这么一个动态执行方法,其他的都是传入参数,这里应该就是初始化pool的入口,如上图:

this.startEvictor(this.getTimeBetweenEvictionRunsMillis());

现在去看看这个方法吧:

如图所述,我们现在就去BaseGenericObjectPool的Evictor类去看看这个任务的具体实现吧。

BaseGenericObjectPool的Evictor

可以看到Evictor果然是一个定时任务实现,里边有个关键调用是ensureMinIdle()方法,现在去看看这个方法吧:

可以看到ensureMinIdle()方法在BaseGenericObjectPool是一个抽象实现,现在就去子类GenericObjectPool。

GenericObjectPool

可以看到是通过LinkedBlockingDeque来存储批量创建好的一批对象。

LinkedBlockingDeque是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除);并且,该阻塞队列是支持线程安全。 此外,LinkedBlockingDeque还是可选容量的(防止过度膨胀),即可以指定队列的容量。如果不指定,默认容量大小等于Integer.MAX_VALUE。

以上就是初始化JedisCluster的过程以及初始化JedisPool的过程。

那么如何获取一个JedisCluster的连接呢?

上图中的获取随机的JedisPool列表的方法getShuffledNodesPool():

这也就是JedisCluster如何获取一个和redis服务端连接的过程。

那么如何从JedisPool中获取一个Jedis对象呢?

JedisPool通过getResource()来获取到Jedis对象。

通过internalPool的borrowObject方法来弹出一个实例供使用。

现在我们就去GenericObjectPool看看borrowObject(弹出对象)这个方法的实现。

GenericObjectPool-->borrowObject()

可以发现通过多个while循环最初弹出一个对象返回。

以上就是一个对象池的弹出对象的过程。

其实对象池算是一种设计模式,比较经典。网上也有很多它的实现。我们也可以从GenericObjectPool所实现的接口就可以看出对象池的一些基本的操作。

总结

通过上面的源码走读,我们知道了JedisCluster会随机获取一个master作为和redis服务端交互的客户端。

ps:由此我们也知道JedisCluster由于设置的都是master。所以当master出现问题时,要做故障转移,那么此时客户端就得重新启动,重新设置最新的master。所以如果我们要做故障转移的支持,可以尝试通过动态的修改nodes那个map里边的master来实现快速的无重启的故障转移。原生的JedisCluster是不支持无重启的故障转移的。

同时在JedisCluster初始化连接的过程中,内部使用JedisPool来初始化redis连接。

而JedisPool的实现又是通过apache commons下的pool2来实现的。而ObjectPool本身就是一个经典的设计模式。核心就是得在池里生成一批对象,就不用在每次调用时都去new一个Jedis。

你可以写个for循环去测试JedisPool和Jedis,据我的测试,性能简直天壤之别,这也正是对象池的美妙之处。

本文分享自微信公众号 - ImportSource(importsource)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FSociety

SQL中GROUP BY用法示例

GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类...

5.1K20
来自专栏怀英的自我修炼

考研英语-1-导学

英二图表作文要重视。总体而言,英语一会比英语二难点。不过就写作而言,英语二会比英语一有难度,毕竟图表作文并不好写。

11510
来自专栏前端桃园

知识体系解决迷茫的你

最近在星球里群里都有小伙伴说道自己对未来的路比较迷茫,一旦闲下来就不知道自己改干啥,今天我这篇文章就是让你觉得一天给你 25 个小时你都不够用,觉得睡觉都是浪费...

20140
来自专栏腾讯社交用户体验设计

ISUX Xcube智能一键生成H5

50920
来自专栏钱塘大数据

理工男图解零维到十维空间,烧脑已过度,受不了啦!

让我们从一个点开始,和我们几何意义上的点一样,它没有大小、没有维度。它只是被想象出来的、作为标志一个位置的点。它什么也没有,空间、时间通通不存在,这就是零维度。

28330
来自专栏微信公众号:小白课代表

不只是软件,在线也可以免费下载百度文库了。

不管是学生,还是职场员工,下载各种文档几乎是不可避免的,各种XXX.docx,XXX.pptx更是家常便饭,人们最常用的就是百度文库,豆丁文库,道客巴巴这些下载...

44030
来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

27640
来自专栏Ken的杂谈

【系统设置】CentOS 修改机器名

17830
来自专栏腾讯高校合作

【倒计时7天】2018教育部-腾讯公司产学合作协同育人项目申请即将截止!

15420
来自专栏钱塘大数据

中国互联网协会发布:《2018中国互联网发展报告》

在2018中国互联网大会闭幕论坛上,中国互联网协会正式发布《中国互联网发展报告2018》(以下简称《报告》)。《中国互联网发展报告》是由中国互联网协会与中国互联...

13350

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励