Redis 高级 Java 客户端 Lettuce 的用法及踩坑经验

作者/分享人:应书澜
向 Ta 提问
毕业于 C9 高校,硕士学历,曾在 IEEE ITS、VSD 等 Top 期刊发表论文。多年研发经验,精通 Java、Python 及 C 语言,擅长预测算法,分布式中间件;曾在华为、阿里巴巴,上海电气等公司重要项目中担任技术负责人或核心研发成员,现专注于中间件技术,同时长期负责招聘。

如果你在网上搜索 Redis 的 Java 客户端,你会发现,大多数文献介绍的都是 Jedis,不可否认,Jedis 是一个优秀的基于 Java 语言的 Redis 客户端,但是,其不足也很明显:Jedis 在实现上是直接连接 Redis-Server,在多个线程间共享一个 Jedis 实例时是线程不安全的,如果想要在多线程场景下使用 Jedis,需要使用连接池,每个线程都使用自己的 Jedis 实例,当连接数量增多时,会消耗较多的物理资源。

与 Jedis 相比,Lettuce 则完全克服了其线程不安全的缺点:Lettuce 是一个可伸缩的线程安全的 Redis 客户端,支持同步、异步和响应式模式。多个线程可以共享一个连接实例,而不必担心多线程并发问题。它基于优秀 Netty NIO 框架构建,支持 Redis 的高级功能,如 Sentinel,集群,流水线,自动重新连接和 Redis 数据模型。

本场 Chat 将介绍以下内容:

  1. Lettuce 重要接口介绍;
  2. Redis单机模式下,Lettuce 的使用;
  3. Redis集群模式下,Lettuce 的使用;
  4. 使用 Lettuce 创建 Redis 集群;
  5. 使用 Lettuce 监控 Redis;
  6. Lettuce 使用过程中的“坑”:堆内存溢出和堆外内存溢出。
已有386人预订
预订达标
文章出炉
     
18.06.25
18.07.06
本场 Chat 文章已出炉,购买后即可阅读文章并获得一张应书澜的读者圈Pass
请务必添加GitChat服务号以查看活动进度及获取活动通知。
查看文章评论/提问
fighting
不值这个钱
应书澜: 欢迎批评指正
清风与我
题主的文章不错,但是我想吐槽一下gitchat的下载pdf功能。建议还是禁止掉吧,在其它浏览器打开要我先下载qq浏览器,好吧我下载,下载了qq浏览器,重复操作,在qq浏览器打开,点击下载,又提示我下载qq浏览器。逆天么要!!!浪费时间和流量!!!
康文
生产上也这么用? 感觉不妥啊 题主还是没有交代清楚 集群模式下主从切换了,客户端是怎么热感知的,如何动态切换的。 其实我是想跟楼主咨询下 netty内存泄漏相关问题的, 当前已经发现这个问题了,处于潜伏期,但是还没爆发。我用的是springboot 集成 spring-boot-starter-data-redis(2.0.3RELEASE) 搭建的单机模式,spring-boot-starter-data-redis(2.0.3RELEASE)依赖的netty是4.1.25Final版,使用这个构造函数new LettuceConnectionFactory(redisStandaloneConfiguration(), lettuceClientConfiguration); 关键代码:【 private RedisStandaloneConfiguration redisStandaloneConfiguration() { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(host); redisStandaloneConfiguration.setPort(port); return redisStandaloneConfiguration; } /** * 单机模式连接工厂 * * @return LettuceConnectionFactory */ @Bean public LettuceConnectionFactory standaloneLettuceConnectionFactory() { LettuceClientConfiguration lettuceClientConfiguration = getLettuceClientConfiguration(); LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration(), lettuceClientConfiguration); lettuceConnectionFactory.afterPropertiesSet(); return lettuceConnectionFactory; } private LettuceClientConfiguration getLettuceClientConfiguration() { GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxTotal(maxActive); poolConfig.setMaxIdle(maxIdle); poolConfig.setMinIdle(minIdle); poolConfig.setMaxWaitMillis(maxWait); return LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig) .shutdownTimeout(Duration.ZERO) .build(); } 】 启动时报(目前不知道如何导致的,虽然不影响启动,但是肯定不妥): 2018-10-07 16:49:36,761 code-app [Finalizer] WARN io.netty.util.internal.logging.Slf4JLogger.warn(131) -io.lettuce.core.resource.DefaultClientResources was not shut down properly, shutdown() was not called before it's garbage-collected. Call shutdown() or shutdown(long,long,TimeUnit) 2018-10-07 16:49:36,893 code-app [main] ERROR io.netty.util.internal.logging.Slf4JLogger.error(171) -LEAK: HashedWheelTimer.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information. Recent access records: Created at: io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:272) io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:216) io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:195)... 最后建议楼主既然是分享开源技术,就不要做强制打赏了, 不利于技术交流。
Ryan
前辈您好: 因为您的头衔我来看您的文章,看完以后收获为0!为何以您这种身份,写出来的技术贴只是在用的阶段?
sdhery
sprint boot 2 redis出错 io.lettuce.core.RedisCommandTimeoutException: Command timed out after 10 second(s) 当第一次访问后,再等10分钟后再访问会报这个错误,但jredis没有这个错误
™ dkcu_💫
请问,如何做到动态刷新连接?
秀丽
楼主好: 既然说Lettuce较Jedis的明显优势是线程安全与节省线程,是否有验证过? 另外Lettuce的两个特定异步和响应式的接口有用过吗? 代码中用的全是sync,这样使用是否有用到了Lettuce的优势与特性呢?
你可能还喜欢
JVM 问题诊断快速入门
火币集团研发中心
面试字节跳动的一点小经验
Wayne
互联网公司热门面试题:如何保证缓存与数据库的双写一致性?
魏武归心2016
面试官问:为什么在项目中使用消息队列!到底是想考什么?
零下
小程序 · 云开发实战:从 0 到 1 快速开发电商小程序
微信极客WeGeek
如何做好性能压测(二) | 性能压测工具选型对比
阿里巴巴中间件
微信扫描登录
关注提示×
扫码关注公众号,获得 Chat 最新进展通知!
入群与作者交流×
扫码后回复关键字 入群
Chat·作者交流群
入群码
该二维码永久有效