前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis-1:一次关于smember和smembers的使用优化

redis-1:一次关于smember和smembers的使用优化

作者头像
千里行走
发布2019-07-03 18:00:34
5.5K0
发布2019-07-03 18:00:34
举报
文章被收录于专栏:千里行走千里行走

在一次业务升级后,发现服务边的不稳定,zabbix各项监控指标相对上线前异常上升。

通过prometheus等监控发现是redis调用大增,看代码在循环里对smember有大量调用。

(1).原因

循环中大量对redis的单次调用会产生大量的redis/io调用,导致业务JVM和redis的cpu的线程上下文和软中断同时飙升。

业务JVM线程上下文和软中断同时飙升原因:

smember的时间复杂度是O(1),很快,jvm大量调用smember后,相关IO也会很快得到返回数据从而进入就绪状态,那么从就绪IO读取数据的线程会始终处于繁忙状态。

而且我们的cpu核数不多,information只有2core,而且jvm访问redis是同步读取,是block的,调用后进入block,cpu必然要切走线程做别的事。

大量/频繁/反复的会进入cpu调度/线程切换的过程中。

大量cpu调度/线程切换–>导致cpu %sy(内核占用cpu时间)飙升。

大量的io事件->导致cpu %si(软中断占用cpu时间)飙升。

关于软中断:

(2).定位过程

循环中大量对redis的单次调用会产生大量的redis/io调用,导致业务JVM和redis的cpu的线程上下文和软中断同时飙升。

top命令:

可以看到%sy(cpu内核时间),%si(cpu软中断时间)非常高,实际上在繁忙时段,%us, %sy, %si可以各占1/3,这个对于%sy, %si非常非常高了,我们希望cpu时间尽可能多的用于%us(cpu 用户态时间)。

zabbix的cpu相关指标:

相关服务的cpu jumps:绿线是上下文切换频率;蓝线是中断频率。

cpu load:相对之前有很大提升。

cpu利用率情况:可以很明显看到cpu的%sy,%si飙升,之所以没有影响线上服务,是因为us%时间够用,仔细观察,%us时间和之前的差不多。

服务线上接口情况:

qps和错误率正常基本没有变化:

接口的延迟时间和往常基本一致:

服务的cpu jumps:

redis实例的cpu load:

redis的cpu 利用率:可以很明显看到cpu的%sy,%si飙升。

观察到这里,只是确定了cpu的使用确实出现了很大的问题,那么接下来我们需要确认cpu为什么高,由何引起。

另外,为什么要先观察grafana和zabbix呢:因为我需要确认一件事:是否影响了线上,决定我是否要回滚,因为回滚代价很高,回滚后不方便定位问题,如果不影响线上,可以短时间内接受。

用两个方法确认这个事情(但可惜最初我没信这个结果,坚持认为redis的smember不会引发,因为速度很快嘛是O(1),但是忽略了IO):

方法一:top -H -p pid

看某个linux下的进程下有哪些线程以及这些线程占用的cpu时间,找到耗费cpu时间最高的线程。

然后将cpu使用率最高的线程id转换为16进制,在jstack pid的结果里去查看这个线程的堆栈:

可以很清晰的看到smember的调用,这次优化上线只有这一处改动,其实这个时候已经可以确认问题了。

方法二:阿里的arthas

arthas安装&使用:https://github.com/alibaba/arthas 这个安装需要高权限,需要运维同学帮忙安装。

使用dashboard命令,有些新东西,有那么7,8个线程始终是RUNNABLE状态,且“永远是”,并且是高耗cpu的线程,一直RUNNABLE说明一直在切换(RUNNING是很难捕获到的)。

再用thread -n 10查找cpu耗损前10的线程堆栈,这个我没有保存现场图,看到的和之前方法一是一样的堆栈,也是smember的堆栈。

原因确认:由于大量调用redis导致io事件爆炸–>从而造成cpu忙不过来。

(3).解决方式

使用smembers一次获取多个数据,JVM内存里运算,规避大量IO事件。

(4).总结

1.循环里不要调用redis

但是像smember这类exist一定是封装在底层的,上层一层层调用很有可能放大,这个只能是在使用的时候注意,同时观察线上的zabbix监控,主要是cpu是否有异动。

我们还在自研框架中集成了prometheus,全方位监控redis的调用。

2.找到一个办法或者参照系去衡量一个服务的cpu健康状态

有的。分两部分来看:

2.1.对于redis的cpu健康状态,我们可以参照redis-passport的cpu指标

只有cpu jumps可以参照,cpu利用率和cpu时间取决于具体怎么用redis,差异太大,看各自的历史曲线。

因为按照正常业务来讲,每次验票都要调用一次redis,这个访问是省不了的,一定量很大,正常服务很难有比这个还高的。如果别的redis的cpu超过了redis-passport的cpu指标,那就需要注意了。下图关键数据脱敏。

2.2.对于nginx来说

由于nginx使用的是epoll,所以软中断个数要远大于线程切换次数,这也是nginx性能很高的一个原因。

2.3.对于一般的应用:

上下文切换次数要高于中断次数。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 千里行走 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • (2).定位过程
  • (3).解决方式
  • (4).总结
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档