Jedis总览Jedis简介源码赏析

Jedis简介

作为Redis官方推荐的三个Java Client之一,Jedis推出时间最早,使用最为广泛(Spring默认使用的Redis Client就是Jedis),同时Star数也遥遥领先于另外两个。和其他Redis Client一样,Jedis通过RESP协议向Redis发送命令请求和解析响应数据。

源码赏析

最新版本的Jedis代码行数超过18K,和Redis本身(20K)处于同一规模。面对如此庞大的项目,分模块阅读是必然之选。由于类的数量太多,本文只在类层面进行简单解读,不会涉及具体的源代码。值得一提的是,虽然Jedis的代码称不上规范,比如全局缺注释、某些类的长度过长,但由于绝大多数方法都很简短,加上清晰的命名和完善的单元测试,代码可读性并没有太大影响。

Core: 核心模块,实现RESP协议

  • Jedis/BinaryJedis 入口类,封装Redis的各种命令。
  • Client/BinaryClient/Connection 与Redis进行具体的交互工作。
  • Protocol, RedisInputStream, RedisOutputStream 实现RESP协议。

Sharding: 提供Partitioning支持

  • ShardedJedis/BinaryShardedJedis: 首先对传入的Key进行Hash计算(默认使用高性能、低碰撞率的MurmurHash算法),然后根据计算结果找到相应的Jedis实例,最后执行命令。

Pool: 提供连接池和Sentinel支持

  • JedisPool: 基于Apache Commons Pool实现的连接池,通过JedisFactory获取Jedis实例。
  • JedisSentinelPool: 通过侦听"switch-master"事件,每当master切换时,调用JedisFactory重新初始化master连接信息。
  • ShardedJedisPool: 与JedisPool类似,通过ShardedJedisFactory获取ShardedJedis实例。

Pipeline: 提供Pipelining事务支持

  • Pipeline: 通过Jedis#pipelined()获取实例。以类型安全的方式获取执行结果,通过BuilderFactory将Object类型的Response转化为期望的结果类型。
    • 非事务模式:构建Response Queue,然后通过Client#getMany()批量获取结果。
    • 事务模式:通过MultiResponseBuilder缓存Response,然后批量获取结果。
  • Transaction: 通过Jedis#multi()获取实例。天然的事务属性,通过Client#getMany()批量获取结果,但无法获取单条命令的结果,且类型非安全。
  • ShardedJedisPipeline: ShardedJedis#pipelined()获取实例。不同于Pipeline和Transaction,由于请求可能落到多个Client上,只能通过Client#getOne()挨个获取结果,类型非安全。

Cluster: 提供Cluster支持

  • JedisCluster/BinaryJedisCluster: 通过JedisClusterConnectionHandler获取Jedis实例,然后执行命令。
  • JedisClusterConnectionHandler & JedisClusterInfoCache: 通过Collections#shuffle()随机返回一个Jedis实例。使用ReentrantReadWriteLock保证更新Cluster的Jedis实例列表时的线程安全性。
  • JedisClusterCommand: 通过retry机制获取有效的Jedis实例,然后再执行命令。

解惑

Q1:为什么有那么多的Binary*类(BinaryJedis, BinaryClient, BinaryShardedJedis, BinaryJedisCluster),它们看上去跟非Binary的子类差不多啊?

A: Binary的父类与非Binary的子类表面的区别是不管是key,还是value,只要涉及字符串语义的参数,前者都用byte[]类型传参,而后者使用String类型。而深层次的原因,我认为跟RESP协议有关,RESP协议是面向字节的协议,对于性能要求极高的场景,使用Binary类有助于提高性能(因为减少了一次String到byte[]的转换)。

Q2:Pipeline, Transaction以及普通的Jedis有何关联?

A: 简单来说,Pipeline和Transaction是批处理运行模式,一次获取多条命令的执行结果,而Jedis只能一条一条获取。而Pipeline和Transaction的区别主要有两点:1)Pipeline同时支持事务模式和非事务模式,而Transaction支持事务模式。2)Pipeline类型安全,Transaction类型非安全。

漫谈

上面提到Jedis的代码规模很大,进一步分析排名靠前的几个大类,可以发现两个明显的特点:

  1. 方法很多,最多的一个类有250+方法,直接结果就是导致类的长度也很长(3000+)
  2. 大多数方法实现不超过5行,并且遵从同一结构

单从缩减代码行数的角度来看,至少可以考虑两种方式:

  1. 使用代码生成工具自动生成享有同一结构的方法
  2. 使用Java 8引入的Functional Interface简化代码

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏非典型技术宅

Swift多线程:使用Thread进行多线程间通讯,协调子线程任务1. Thread的三种建立方式2. Thread的基本使用3. 使用NSCondition实现线程间通讯4. pthread

21720
来自专栏屈定‘s Blog

(转)JAVA拾遗--关于SPI机制

JDK提供的SPI(Service Provider Interface)机制,可能很多人不太熟悉,因为这个机制是针对厂商或者插件的,也可以在一些框架的扩展中看...

46130
来自专栏Linyb极客之路

工作流引擎之activiti入门

在解释activiti之前我们看一下什么是工作流。 工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个...

2.5K40
来自专栏美团技术团队

Android增量代码测试覆盖率工具

前言 美团点评业务快速发展,新项目新业务不断出现,在项目开发和测试人员不足、开发同学粗心的情况下,难免会出现少测漏测的情况,如何保证新增代码有足够的测试覆盖率是...

75390
来自专栏腾讯Bugly的专栏

【团队分享】刀锋铁骑:常见Android Native崩溃及错误原因

王竞原,负责网游刀锋铁骑项目,高级开发工程师,使用C++已有10年,非常喜欢C++,特别是C++11。希望能与广大的C++爱好者多交流。 一、什么是Androi...

52330
来自专栏C/C++基础

腾讯2016春季校园实习招聘技术岗初试(一面)问题汇总(CC++后台)

2016.4.11日广州参加了腾讯的CC++后台技术一面,安全技术类的面试。面试官人很温和,经历了大概70分钟的问答,特将遇到的面试问题汇总如下,自己总结学习,...

9110
来自专栏Java帮帮-微信公众号-技术文章全总结

JavaWeb08-XML,tomcat,HTTP轻松入门

XML&tomcat&HTTP 一.XML基础知识 1. xml介绍 XML 指可扩展标记语言(EXtensible Markup Language),也是一种...

41290
来自专栏更流畅、简洁的软件开发方式

Step By Step 一步一步写网站[1] —— 填加数据

填加数据是一个项目必不可少的部分,也是一个基础操作,使用也是最频繁的。 那么您是怎么实现添加数据的呢? 添加数据可以分为几种情况。 1、单表添加,不需要事务。...

215100
来自专栏java一日一条

深入理解 Java 中的 try-with-resource

众所周知,所有被打开的系统资源,比如流、文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故。

16820
来自专栏mini188

Ignite性能测试以及对redis的对比

测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像。测试方法很...

68070

扫码关注云+社区

领取腾讯云代金券