IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis为什么慢了(上) -> 正文阅读

[大数据]Redis为什么慢了(上)

Redis为什么慢了

Redis作为我们常用的缓存中间件广泛应用到生产中,应用过程中或多或少可能会出现一系列的性能问题,Redis响应速度变慢了如何处理呢?命令执行变慢了如何处理呢?Redis某个时间段突然变慢了之后又恢复正常了如何排查呢?等等这篇文章来记录下Redis性能问题的排查方案。

Redis基线测试

某业务逻辑处理变慢了首先需要考虑的是到底是不是Redis自身影响的呢?因为整个业务链路包括多个参与者(APP、Redis、Mysql等等)每个参与者的阻塞都有可能导致整个业务的性能问题,这时需要知晓每个参与者的响应时间,如果真是Redis链路响应过慢,就可以进行接下来的排查。

Redis响应过慢判断指标可以通过基准性能来确定

什么是基准性能呢?

基准性能指的就是在一个系统在低压力、无干扰下的基本性能,不同的服务器配置,基准性能不同,不能一概而论

如下所示,得到100秒内的最大延时(测试机器配置较低,指标仅参考

###?表示100秒内的响应延迟
###?如果redis是默认端口可以采用下面的命令,如果端口非默认需要指定端口./redis-cli?-p?port?--intrinsic-latency?100
[root@zzf993?bin]#?./redis-cli?--intrinsic-latency?100
Max?latency?so?far:?1?microseconds.
Max?latency?so?far:?7?microseconds.
Max?latency?so?far:?12?microseconds.
Max?latency?so?far:?34?microseconds.
Max?latency?so?far:?70?microseconds.
Max?latency?so?far:?3140?microseconds.
Max?latency?so?far:?4210?microseconds.
Max?latency?so?far:?23074?microseconds.
Max?latency?so?far:?104617?microseconds.

2165236605?total?runs?(avg?latency:?0.0462?microseconds?/?46.18?nanoseconds?per?run).
Worst?run?took?2265206x?longer?than?the?average?latency.

我们还能使用以下命令得到最小、最大、平均延时等

###?i表示间隔多久统计一次单位秒
[root@zzf993?bin]#?./redis-cli?--latency-history?-i?1
min:?0,?max:?2,?avg:?0.27?(98?samples)?--?1.01?seconds?range
min:?0,?max:?7,?avg:?0.33?(96?samples)?--?1.00?seconds?range
min:?0,?max:?2,?avg:?0.21?(97?samples)?--?1.00?seconds?range
min:?0,?max:?2,?avg:?0.18?(97?samples)?--?1.00?seconds?range
min:?0,?max:?6,?avg:?0.30?(94?samples)?--?1.01?seconds?range
min:?0,?max:?1,?avg:?0.17?(98?samples)?--?1.01?seconds?range
min:?0,?max:?1,?avg:?0.24?(97?samples)?--?1.00?seconds?range
min:?0,?max:?2,?avg:?0.19?(98?samples)?--?1.01?seconds?range

知道基准性能概念后,我们可以按照如下步骤判断

  • 找配置相同的服务器得到基准性能。

  • 在可能变慢实例的服务器上得到最大延时。

  • 如果实例的最大延时是基准性能延时的2倍以上,说明是Redis实例内部的问题,可以继续排查。

Redis变慢排查方向

Redis实例确实出现变慢的情况,这时需要更加细致的排查,一般分为三大块Redis自身特性、文件系统、操作系统

Redis自身特性的影响

慢查询命令

在Redis中慢查询命令一般分为两类

  • 如SORT、聚合操作(SUNION、ZUNIONSTORE、SINTER)、KEYS等,因为操作内存数据需要花费更多的CPU资源。

  • 分段查询一次查询大量数据如(LRANGE key 0 N,N足够大)Redis需要返回给客户端大量的数据,更多的时间花费在网络传输上。

这两者的操作都是在主线程中完成,都有可能造成网络阻塞,但这只是有可能,我们可以通过慢查询日志slowlog观察,慢查询日志可以在redis.conf文件中配置参数slowlog-log-slower-than N表示执行时间超过N毫秒开始记录慢日志,当N=0时表示所有的命令都会记录到慢查询日志中测试时可以这样设置,查询慢日志命令是SLOWLOG get N获取最新的多少个慢查询日志,结果如下

127.0.0.1:6379>?SLOWLOG?get?5
1)?1)?(integer)?1946?###?每个慢查询条目的唯一的递增标识符
?? 2)?(integer) 1651750547 ###?处理记录命令的unix时间戳。
?? 3)?(integer) 19 ###?命令执行所需的总时间,以微秒为单位。
???4)?1)?"SLOWLOG"?###?组成该命令的参数数组
??????2)?"get"
??????3)?"20"
???5)?"127.0.0.1:57602"
???6)?""

当slowlog中出现上述慢查询命令时,我们可以进行如下优化

  • 在服务端尽量不进行聚合运算等复杂操作,复杂操作交由客户端完成。

  • 如果是分段查询,可以少量多次查询,避免Redis的阻塞。

操作bigkey

如果在慢日志中包含有get、set等命令那就需要考虑bigkey的情况,因为get、set命令时间复杂度是O(1),在slowlog-log-slower-than N配置设置正常的情况下是不会出现这种情况的,最大可能就是bigkey,我们可以采用命令查看实例的bigkey分布情况

###?如果redis是默认端口可以采用下面的命令,如果端口非默认需要指定端口./redis-cli?-p?6379?--bigkeys

[root@zzf993?bin]#?./redis-cli?--bigkeys

#?Scanning?the?entire?keyspace?to?find?biggest?keys?as?well?as
#?average?sizes?per?key?type.??You?can?use?-i?0.1?to?sleep?0.1?sec
#?per?100?SCAN?commands?(not?usually?needed).
##?得到比目前统计要大的bigkey(如果新加入的key比上面的bigkey要大就会统计到,如果小就不会统计)
[00.00%]?Biggest?list???found?so?far?'"database"'?with?3?items
[00.00%]?Biggest?string?found?so?far?'"key2"'?with?4?bytes
[00.00%]?Biggest?list???found?so?far?'"test3"'?with?13?items
[00.00%]?Biggest?string?found?so?far?'"name"'?with?8?bytes

--------?summary?-------

Sampled?7?keys?in?the?keyspace!
Total?key?length?in?bytes?is?32?(avg?len?4.57)

Biggest???list?found?'"test3"'?has?13?items
Biggest?string?found?'"name"'?has?8?bytes

2?lists?with?16?items?(28.57%?of?keys,?avg?size?8.00)
0?hashs?with?0?fields?(00.00%?of?keys,?avg?size?0.00)
5?strings?with?22?bytes?(71.43%?of?keys,?avg?size?4.40)
0?streams?with?0?entries?(00.00%?of?keys,?avg?size?0.00)
0?sets?with?0?members?(00.00%?of?keys,?avg?size?0.00)
0?zsets?with?0?members?(00.00%?of?keys,?avg?size?0.00)

如果是查询存在bigkey那么需要优化业务逻辑解决,如果是删除bigkey阻塞,可以优化如下

  • 如果Redis版本是4.0之后的那么将DEL改为UNLINK解决,该命令会在另一个线程中回收内存,非阻塞操作。

  • 如果Redis版本是4.0之后的也可以采用lazy-free方案,将redis.conf中设置lazyfree-lazy-server-del yes属性,效果和UNLINK类似。

即使删除有UNLINK方案和lazy-free同样需要注意的是在业务中应避免bigkey的存在,在很多场景bigkey都有性能限制。

key的过期操作

key过期后的删除机制分为两种情况,定时自动删除和被动删除。

  • 被动删除:是指当客户端访问某个key时,会判断这个key的是否已经过期,如果过期需要从实例中删除。

  • 定时自动删除:Redis中存在一个定时任务,默认每隔100毫秒会自动从过期哈希表中随机取出20个key(1秒就是200个),然后删除key,当过期key的比例超过25%时,将重复删除过程,直到过期key的比例小于25%为止。

定时自动删除这里的比例超过25%后重复删除过程这里会在主线程的运行,一但过期key的比例高那么将阻塞主线程。

而过期key的比例高换句话说就是key的集中过期,导致了定时自动删除拖延主线程任务处理时间,这个场景大部分出现在EXPIREAT给大量key设置相同的过期时间,解决办法有如下方案

  • 将过期时间上一个小的随机时间,确保单个时间点上不会有大量key过期的情况。

  • 如果Redis是4.0以上版本,可以开启lazy-free异步执行键值删除逻辑

    ###?redis.conf中配置默认no不开启
    lazyfree-lazy-expire?yes
    
    

我们还需要关注实例过期key的数量,如果新增需要立即排查,我们可以通过如下命令

###?统计的是实例过期key的数量,如果激增表明key有集中失效的情况
[root@zzf993?bin]#?./redis-cli?info?|?grep?expired_keys
expired_keys:1

另外补充注意点,如果过期删除时删除的是一个bigkey,这时Redis的命令执行延时高,但是慢日志不会记录,主要耗时就在执行Redis的key值删除的逻辑上。

Redis内存达到maxmemory

在redis.conf文件中配置了最大内存后 maxmemory <bytes>如果内存使用量超过这个配置,那么内存淘汰机制就将触发,内存淘汰机制需要先按照淘汰规则淘汰部分key后才能让新数据写入,自然操作的延迟会增加。

另外需要注意的是,内存淘汰和删除是类似的,如果淘汰的是一个bigkey那么可能导致Redis命令的执行延时高

内存淘汰规则如下所示

  • noeviction:不淘汰任何 key,实例内存达到 maxmeory 后,再写入新数据直接返回错误

  • allkeys-lru:淘汰目标是所有的key,淘汰最近访问最少的。

  • allkeys-random:淘汰目标是所有的key,随机淘汰key。

  • allkeys-ttl:淘汰目标是所有的key,淘汰即将过期的 key。

  • volatile-lru:淘汰目标是设置了过期时间的 key,淘汰最近访问最少的。

  • volatile-random:淘汰目标是设置了过期时间的 key,随机淘汰key。

  • allkeys-lfu:淘汰目标是所有的key,淘汰访问频率最低的 key(4.0+版本支持)

  • volatile-lfu:淘汰目标是设置了过期时间的 key,只淘汰访问频率最低(4.0+版本支持)

lru规则就是每次从实例中随机抽取一定数量的key,淘汰一个最少使用的,然后将其余的放入到一个池子中,继续随机从实例中随机抽取一定数量的key,并与之前池子中的key作比较,选取一个最少使用的反复执行,将内存占用控制到maxmemory以下。

lfu规则是对lru的改进,lfu是保留访问相对频繁的key,丢弃访问不频繁的key,而lru是去淘汰最近访问最少的,相对概念稍有不同。

如果出现上述场景,可以进行如下调整

  • 拆分实例将淘汰key的压力均摊到多个实例上。

  • 淘汰策略变更,如果业务允许可以采取随机淘汰策略,随机淘汰策略比lru或lfu淘汰速度快。

  • 如果Redis版本是4.0以上版本,可以开启lazy-free方案修改redis.conf文件lazyfree-lazy-eviction yes

频繁短连接

如果客户端和服务端连接采用短连接的形式那么Redis的部分性能消耗在连接建立和释放上,可能会造成业务延迟,所以业务应用建议尽量使用长连接的形式。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-08 08:10:56  更:2022-05-08 08:14:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:35:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码