通过《redis功能实现》的了解,并且redis官方提供了《JAVA Redis客户端》。其中Jedis,lettuce提供对redis基本封装, redisson为高级封装。
jedis主要采用连接池+bio的方式完成jedis的通试。
// redis.clients.jedis.Jedis最终会调用以下方法 // redis.clients.jedis.Connection public void sendCommand(final ProtocolCommand cmd, final byte[]... args) { try { // 以bio的方式连接 connect(); // 组装命令向outputStream写入协议 Protocol.sendCommand(outputStream, cmd, args); } catch (JedisConnectionException ex) { // ... } }
// JedisPool最终会通过些访求进行初始化 // poolConfig 实现类 JedisPoolConfig 主要提供连接commons.pool2连接池的配置参数 // factory 实现类 RedisPooledObjectFactory 主要实现commons.pool2资源创建接口PooledObjectFactory public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) { this.internalPool = new GenericObjectPool<>(factory, poolConfig); }
public static void main(String[] args) throws Exception { JedisPool jedisPool = new JedisPool("localhost", 6379); // 不可以多线程使用 Jedis jedis = jedisPool.getResource(); System.out.println(jedis.get("foo")); jedis.close(); }
lettuce使用netty + nio,复用同一个连接。《netty连接redis例子》
public static void main(String[] args) throws Exception { RedisURI redisUri = RedisURI.Builder.redis("localhost") .withDatabase(1) .build(); RedisClient client = RedisClient.create(redisUri); // connection普通命令多线程复用,但是使用事务不可以 StatefulRedisConnection<String, String> connection = client.connect(); RedisCommands<String, String> sync = connection.sync(); System.out.println(sync.get("foo")); connection.close(); }
redisson也是使用netty + nio,复用同一个连接。《netty连接redis例子》
public static void main(String[] args) { RedisClientConfig redisClientConfig = new RedisClientConfig(); redisClientConfig.setAddress("redis://127.0.0.1:6379"); RedisClient client = RedisClient.create(redisClientConfig); // connection普通命令多线程复用,但是使用事务不可以 RedisConnection redisConnection = client.connect(); // 封装了个命令对象 // @see RedisCommands.SET RedisCommand<String> SET = new RedisCommand<>("SET"); String setValue = redisConnection.sync(SET, "foo", "yoyo1"); System.out.println(setValue); RedisCommand<String> GET = new RedisCommand<>("GET"); String value = redisConnection.sync(GET, "foo"); System.out.println(value); }
针对redis java client,从多角度进行选型对比
Jedis | Lettuce | Redisson | |
---|---|---|---|
地址 | https://github.com/xetorthio/jedis | https://lettuce.io/ | https://github.com/redisson/redisson |
what | 且健全的redis java客户端,支持redis的所有特性和命令,如事务、管道、发布订阅。 | 线程安全的redis客户端,封装同步、异步、交互API。不执行阻塞和事务操作时,多线程可共享连接。 | 线程安全的redis客户端,支持多场景,提供基于redis的某些分布式服务解决方案 |
实现与使用 | 实现简单,使用简单 | 实现较复杂,使用简单 | 实现复杂,使用简单 |
网络 | 阻塞IO | Netty | Netty |
redis命令特性支持 | redis命令与特性提供健全的支持 | redis命令与特性支持 | redis命令和特性支持 |
抽象封装程度 | 没有做特别的抽象,特性使用是否正确依赖使用者。 | 同步、异步、交互场景封装 | 丰富的数据模型、分布式服务、特性的封装,第三方框架的扩展实现 |
操作的维度 | 指令维度的操作 | 指令维度的操作 | 使用对象、服务将redis指令和业务分离,对象维度的操作,使用更方便,没有使用指令灵活,支持redisClient执行指令;分布式服务特性缺乏管理平台。 |
redis连接 | 每次操作均需要从连接池中获取连接,线程间不可以共享连接,高并发时需要考虑连接过多对client和server的影响。 | 共享连接,连接是long-lived和线程安全的,而且自动重连 | 共享连接 |
client分片 | 支持,提供实现 | 不支持,未提供实现 | 不支持,针对特殊数据模型提数据分片 |
read slave | 未找到使用slave执行read指令的API,但可以自行实现 | 支持slave执行read指令 | 支持slave执行read指令 |
排他+超时 | 支持 | 支持 | 需要使用封装的数据模型 |
社区维护 | 社区维护好,版本更新快 | 社区维护一般,版本更新较慢 | 分为企业版和开源版,维护好,版本更新快 |
推荐直接使用Redisson