本周扑火之 redis 不给力
Social Graph 高速接口,当前我们使用 Redis 存储。但在实现的过程中,发现了诸多的问题。
48G 内存的机器上部署了 2 个 Redis 进程,一个 Redis 占用超过 21 G 内存后,在快速写入的过程中同时进行一次 bgsave ,就将机器给弄挂了(微博上的直播)。我们对 Redis 的监控远不如对 Mysql 之类的完善,以至于 Redis 机器假死,居然没有触发任何的报警。
在经过几天的 debug 后,终于找到了问题所在,复杂的上线流程:源码 svn 合 trunk,发布 jar 包到二进制 svn,配置文件按 IDC 配置,打 tag,上线,发布,终于有一个小小的地方没有控制住,没有进行最终的确认,导致发到线上的配置文件是源码目录中的测试配置,导致 redis hash 出错。而严重缺乏的监控,也没能发挥“最后一道防线”的作用,任由问题越演越烈(微博上的直播)。
按说找到了问题所在,修复起来就很容易了。但 billion 级别的数据,重新初始化,远比想象的复杂。从上周五开始重新灌数据,周六在家习惯性的用 iphone 登陆看 log 。一看吓一跳:按那个速度计算,重新初始化需要一个月才能完成。而第一次初始化,才花了几十个小时啊。
首先怀疑是资源的问题:打电话找运维,确认 redis 没有问题,数据库没有问题,queue 队列没有问题。那就是程序的问题了。用 Btrace 一层一层的跟踪,最后定位在 jedis.hset 和 jedis.hdel 上:一次 hset 或 hget 居然需要超过 100 ms (微博上的记录)。周一到单位,给代码加了详细的时间 log ,也印证了周末 Btrace 的结果。这是为什么呢?
还是怀疑 redis 服务器的问题。写了一个简单的压力测试代码去压测试用的redis,在本机上运行,果然每秒才 4000 来次 hget、hset 。可是拿到服务器上一跑,轻松的就到了 4 万多次。所以本机上慢,应该是网络带宽的原因。
接下来只能怀疑是程序代码的问题。但在测试环境下回滚版本,换客户端库,各种手段用完都找不到问题之后,只能将目光转向线上环境。
直接用压力测试代码压线上服务器,果然也慢。继续看 log ,似乎慢的请求有一个共性:某个时间点,几十个请求的耗时是一样的,都是类似 127ms,132ms 这样的。如果是真实的处理耗时,不应该会如此雷同才对,那么就应该是排队等待耗时了。这一批请求应该是同时发起的,因为某种原因,一同在某个地方排队,等轮到它们的时候,真实的处理耗费的时间连 1 ms 都不到,所以在 log 里看来,耗时如此相似。接下来的问题就是,为什么会排队?在哪排队?后面一个问题比较好回答,Redis 是单线程的,按照网络接收到的包的顺序处理请求,前一个请求没有处理完之前,后面的请求都在 server 的 tcp/ip buffer 里排队,等待处理。那剩下的就只有一个问题了:为什么会有排队现象?
仔细看业务代码,终于找到一个可疑的地方:hgetAll 。难道是一个 hgetAll 堵住了后面所有的请求?压测的脚本一般都只压 get,set,顶多也就试试 hget,hset,肯定不会压 hgetAll 这么变态的命令的。而用 strace 查看 redis server 的状态,也只能看到网络调用耗时。那么也就只能这么解释了:hgetAll 命令占用了大量的网络带宽,导致它完成之前,其它的命令的回包都在 tcp buffer 里面堵着了。
试着修改了一下业务处理逻辑,减少了部分冗余的 hgetAll 调用,果然速度有所提升。虽然还是没有第一次的时候快,但好歹升到了一个可接受的范围了。
接下来,就是重构 redis 相关的代码,让下次的 debug 不至于这么被动。有时间顺便在测试环境下重现一下这种情况,以确定自己的怀疑。
建议继续学习:
- redis源代码分析 - persistence (阅读:31229)
- Redis消息队列的若干实现方式 (阅读:10772)
- 基于Redis构建系统的经验和教训 (阅读:9385)
- 浅谈redis数据库的键值设计 (阅读:8348)
- redis运维的一些知识点 (阅读:7517)
- redis在大数据量下的压测表现 (阅读:7441)
- Redis和Memcached的区别 (阅读:6893)
- Redis作者谈Redis应用场景 (阅读:6626)
- redis 运维实际经验纪录之一 (阅读:6533)
- 记Redis那坑人的HGETALL (阅读:6373)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:唐福林 来源: 福林雨-博客
- 标签: redis
- 发布时间:2011-05-25 12:35:12
- [69] Twitter/微博客的学习摘要
- [65] 如何拿下简短的域名
- [64] IOS安全–浅谈关于IOS加固的几种方法
- [62] find命令的一点注意事项
- [62] android 开发入门
- [62] Go Reflect 性能
- [60] 流程管理与用户研究
- [58] 图书馆的世界纪录
- [58] 读书笔记-壹百度:百度十年千倍的29条法则
- [58] Oracle MTS模式下 进程地址与会话信