1.服务器排查
1.1磁盘排查
使用df(disk file) -h获取磁盘状态
使用df -lh 查看文件大小
使用du(disk use) -u查看文件夹大小
1.2CPU排查
使用top命令查看进程状态
使用 top -hc 查看线程状态
1.3内存排查
利用free -h 查看内存使用情况
2.java问题排查
2.1线程问题
使用jstack命令查看jvm运行状态
2.2内存问题
(1)指定合适得内存参数,-Xmx,-Xms
(2)导出OOM快照
(3)利用MAT工具进行分析
里面有直方图,折线图可以查找大对象问题
里面有泄漏点可以分析内存泄漏问题
3.redis层面
3.1大key问题
3.1.1是什么?
value占用内存过大 默认情况下:认为String类型的大小大于1MB,集合的大小大于1w个
3.1.3危害?
1)内存不足 2)阻塞请求 3)影响redis性能 4)网络阻塞 5)主从同步延迟 6)数据倾斜
3.1.4排查?
1. 使用Redis内置功能发现大Key问题
1)使用debug object命令
使用debug object 命令对key进行分析序列化长度。其中serializedlength的值为该key的序列化长度,此长度不等于它内存真实长度。
缺点:阻塞请求。 不推荐
2)MEMORY USAGE命令
Redis自4.0起提供了MEMORY USAGE命令来帮助分析Key的内存占用,相对debug object它的执行代价更低,但由于其时间复杂度为O(N)因此在分析大Key时仍有阻塞风险。
3)使用获取长度命令
结构 | 命令 | 时间复杂度 | 描述 |
---|---|---|---|
String | STRLEN | O(1) | 获取String结构的长度 |
Hash | HLEN | O(1) | 获取hash结构的长度 |
Set | Scard | O(1) | 获取set结构长度 |
Zset | Zcard | O(1) | 获取zset结构长度 |
List | LLen | O(1) | 获取list长度 |
String测试:
hash结构测试:
set结构测试:
zset结构测试:
list结构测试:
通过以上Redis内置命令我们可以方便且安全的对Key进行分析而不会影响线上服务,但由于它们返回的结果非Key的真实内存占用数据,因此不够精确,仅可作为参考。
2). 通过Redis官方客户端redis-cli的bigkeys参数发现大Key
如果你并无明确的目标Key用于分析,而是希望通过工具找出整个Redis实例中的大Key,此时redis-cli的bigkeys参数能够方便的帮你实现这个目标。
Redis提供了bigkeys参数能够使redis-cli以遍历的方式分析整个Redis实例中的所有Key并汇总以报告的方式返回结果。该方案的优势在于方便及安全
缺点也非常明显:分析结果不可定制化。
bigkeys仅能分别输出Redis六种数据结构中的最大Key,如果你想只分析STRING类型或是找出全部成员数量超过10的HASH Key,那么bigkeys在此类需求场景下将无能为力。
3)使用开源工具发现大Key
使用redis-rdb-tools工具以定制化方式找出大Key
如果你希望按照自己的标准精确的分析一个Redis实例中所有Key的真实内存占用并避免影响线上服务,在分析结束后得到一份简洁易懂的报告,redis-rdb-tools是非常好的选择。
原理:该工具能够对Redis的RDB文件进行定制化的分析,但由于分析RDB文件为离线工作,因此对线上服务不会有任何影响,这是它的最大优点但同时也是它的最大缺点:离线分析代表着分析结果的较差时效性。对于一个较大的RDB文件,它的分析可能会持续很久很久。
3.1.5大key排查方式整理总结
(1)使用开源命令进行排查
使用debug object命令分析key长度,长度不准。缺点:阻塞其他请求 不推荐
使用memeory usage命令分析key长度,时间复杂度为o(n),也会有阻塞的场景
使用strlen,hlen,scard,zcard,llen获取key长度,时间复杂度更低。
以上缺点:仅仅是对长度分析,不能对value大小分析。
(2)使用redis客户端redis-cli的bigkey进行分析
缺点:不能定制化分析,bigkey展示是各个类型的key
(3)使用开源工具 redis-rdb-tools分析
优点:采用异步对rdb文件进行分析
缺点:实时性会有问题
3.1.6解决方案
(1)对大Key进行拆分;分治思想,将key进行拆分,降低单key大小,获取时候可以使用mget批量获取.
(2)设置合适的过期时间
(3)设置合适的内存淘汰算法
(4)数据压缩,value使用压缩算法
(5)对大Key进行清理 Redis自4.0起提供了UNLINK命令,该命令能够以非阻塞的方式缓慢逐步的清理传入的Key,通过UNLINK,你可以安全的删除大Key甚至特大Key。
(6)时刻监控Redis的内存水位 如:Redis内存使用率超过70%,Redis内存1小时内增长率超过20%等。
(7)对失效数据进行定期清理 例如我们会在HASH结构中以增量的形式不断写入大量数据而忽略了这些数据的时效性,这些大量堆积的失效数据会造成大Key的产生,可以通过定时任务的方式对失效数据进行清理。在此类场景中,建议使用HSCAN并配合HDEL对失效数据进行清理,这种方式能够在不阻塞的前提下清理无效数据。
3.2热key问题
3.2.1是什么?
在某个Key接收到的访问次数、显著高于其它Key时,我们可以将其称之为热Key,常见的热Key。
3.2.2危害?
1)请求集中,网络带宽问题
2)请求过多,单实例并发承受不住会崩溃
3)数据击穿,造成雪崩
3.2.3排查?
1)通过Redis官方客户端redis-cli的hotkeys参数发现热Key 缺点不能定制化分析
2)通过业务层定位热Key
指向Redis的每一次访问都来自业务层,因此我们可以通过在业务层增加相应的代码对Redis的访问进行记录并异步汇总分析。该方案的优势为能够准确并及时的分析出热Key的存在,缺点为业务代码复杂度的增加,同时可能会降低一些性能。
3)使用monitor命令在紧急情况时找出热Key
Redis的monitor命令能够忠实的打印Redis中的所有请求,包括时间信息、Client信息、命令以及Key信息。在发生紧急情况时,我们可以通过短暂执行monitor命令并将输出重定向至文件,在关闭monitor命令后通过对文件中请求进行归类分析即可找出这段时间中的热Key。
由于monitor命令对Redis的CPU、内存、网络资源均有一定的占用。因此,对于一个已处于高压状态的Redis,monitor可能会起到雪上加霜的作用。同时,这种异步收集并分析的方案的时效性较差,并且由于分析的精确度取决于monitor的执行时间,因此在多数无法长时间执行该命令的线上场景中本方案的精确度也不够好。
3.2.3解决方式
(1)在Redis Cluster结构中对热Key进行复制
在Redis Cluster中,热Key由于迁移粒度问题造成请求无法打散使单一node的压力无法下降。此时可以将对应热Key进行复制并迁移至其他node,例如为热Key foo复制出3个内容完全一样的Key并名为foo2,foo3,foo4,然后将这三个Key迁移到其他node来解决单一node的热Key压力。
该方案的缺点在于代码需要联动修改,同时,Key一变多带来了数据一致性挑战:由更新一个Key演变为需要同时更新多个Key,在很多时候,该方案仅建议用来临时解决当前的棘手问题。
(2)采用读写分离架构 读写分离架构会产生不可避免的延迟,此时会有读取到脏数据的问题,因此,在读写压力都较大写对数据一致性要求很高的场景下,读写分离架构并不合适。
(3)多级缓存机制,在前面做一层缓存机制,减轻redis的压力
(4)数据预热机制 提前将key预热。
3.3 redis缓存击穿,缓存穿透,缓存雪崩
缓存穿透:数据库中没有,缓存中没有
解决方案:
(1)接口端过滤一些无效请求
(2)空值缓存
(3)布隆过滤器
缓存击穿:数据库中有,缓存中过期了
解决方案:
(1)分布式锁,避免很多请求打到数据库
(2)提前对热点数据进行设置
(3)监控数据,及时调整。
缓存雪崩:大片的key同时过期,数据库中有,缓存没有
解决方案:
(1)将不同的key的过期时间打散
(2)使用多级架构 使用nginx缓存+redis缓存+其他缓存,不同层使用不同的缓存,可靠性更强
(3)分布式锁