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 不至于这么被动。有时间顺便在测试环境下重现一下这种情况,以确定自己的怀疑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值