Code前端首页关于Code前端联系我们

移民者的Redis教程(二十):性能提升与故障排除

terry 2年前 (2023-09-26) 阅读数 93 #后端开发

前言

你是否遇到过以下情况:

  • 在Redis中执行同一个命令时,为什么有时会很快却很慢的答案?
  • 为什么Redis执行SET和DEL命令需要这么长时间?
  • 为什么我的Redis突然变慢然后又恢复了?
  • 为什么我的Redis连续运行了很长时间,突然在某个时刻开始变慢?

Redis 真的很慢吗?

首先在开始之前,你需要知道Redis是否真的很慢?

如果您发现您的业务服务API 变得越来越长,您需要首先查看服务内部,看看哪些链接正在减慢整个服务的速度。

更高效的方式是在服务内部添加链路监控(也可以打印日志),即在进入和退出访问外部依赖的服务时,记录每个请求对外部依赖的响应延迟。

如果你发现Redis功能之间的关系变得非常长,那么你需要关注从业务服务到

  • 的链接

    Redis该链路慢可能有两个原因:

    • 企业服务器与Redis服务器之间存在网络问题,如网络质量差、数据传输延迟等。包裹。 、丢包等;
    • Redis本身存在问题,需要更多调查Redis为什么慢。

    这两种坑我都遇到过,哈哈哈

    第一种出现的概率比较小。如果是,请联系网络运维。我们的文章主要讨论第二种情况。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。

    什么是基本表演?

    除了网络因素之外,如何检查Rediso是否真的很慢?首先需要对Redis进行性能测试,了解Rediso在生产环境服务器上的性能。基线性能是指Redis 在负载正常的机器上,最大响应延迟和平均响应延迟是多少? ? (不!)。 Redis提供了慢日志命令的统计功能,记录任何执行时间较长的命令。
    redis.config文件:日志大小:config 设置 Slowlog-Log-Log-Log-Log-Slow-Slower 5000

  • on SET Slowlog -max-len 500
  • 127.0.0.1:6379> SLOWLOG get 5
    1) 1) (integer) 32693       # 慢日志ID
       2) (integer) 1593763337  # 执行时间戳
       3) (integer) 5299        # 执行耗时(微秒)
       4) 1) "LRANGE"           # 具体执行的命令和参数
          2) "user_list:2000"
          3) "0"
          4) "-1"
    

    通过查看慢度日志,我们知道哪些命令在什么时间执行需要时间。经常使用

    • 复杂命令或更高O(N),例如key、flushdb❀❀。
    • 在难度中使用命令O(N),但是N的值非常大。例如:hgetall、lrange、smembers、zrange等。不能使用,但需要明确N的值。

    第一种情况变慢的原因是Redis在使用内存数据时复杂度太大,需要更多的CPU第二个原因。导致慢的原因是Redis需要返回太多给客户端

  • slowlog-log-slower-than #它决定要对执行时间大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的命令进行记录。
    slowlog-max-len #它决定 slowlog 最多能保存多少条日志,当发现redis性能下降的时候可以查看下是哪些命令导致的。
    
    ,花费更多时间》关于汇编和数据协议在传输中网络。 ? 示例中CPU的使用率非常高,可能是因为命令的使用过于复杂
  • Redis 是一个单线程客户端应用程序。如果你经常使用上面的命令,那么当Redis反转客户端请求时,只要上一个命令存在,就会生成下一个请求。对于顾客来说,延误会更长。 ?然后你必须问自己你的实例是否写了 bigkey
    Redis 写入数据时,需要为新数据
    分配内存。相应地,当从Redis写入数据时,从删除数据时,会释放对应的内存空间。如果的键写得很大,那么♿❿❿这个 键,释放内存需要更多时间。这种类型的key通常称为bigkey
    如何查看示例中的bigkey分布?
    • 第一种:Redis提供了检查bigkey的命令。您可以通过运行以下命令来检查bigkey。 的分布:
    $ redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01
    ...
    -------- summary -------
    Sampled 829675 keys in the keyspace!
    Total key length in bytes is 10059825 (avg len 12.13)
    
    Biggest string found 'key:291880' has 10 bytes
    Biggest   list found 'mylist:004' has 40 items
    Biggest    set found 'myset:2386' has 38 members
    Biggest   hash found 'myhash:3574' has 37 fields
    Biggest   zset found 'myzset:2704' has 42 members
    
    36313 strings with 363130 bytes (04.38% of keys, avg size 10.00)
    787393 lists with 896540 items (94.90% of keys, avg size 1.14)
    1994 sets with 40052 members (00.24% of keys, avg size 20.09)
    1990 hashs with 39632 fields (00.24% of keys, avg size 19.92)
    1985 zsets with 39750 members (00.24% of keys, avg size 20.03)
    

    **每类数据(5种key类型,不是全部数据)**安装的最大内存/哪个key元素最多,以及每种数据的Average比例和大小输入整个样本/项目数量。使用此命令的原理是redis在内部执行Scan命令,通过实例中的所有键进行迭代,然后执行 ,分别表示关键类型。 HLEN、SCARD、ZCARD

    用于获取String类型的长度和类型容器的元素数量(,,

    )。 。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。

    执行该命令时,请注意问题2:

    • 在线实例上进行bigkey扫描时,Redis的OPS(每秒操作数)会突然增加。为了减少扫描过程中对Redis的影响,建议通过定义参数-i来控制扫描频率。 表示扫描过程中每次检查后剩余的时间间隔,单位为秒。在搜索结果
    • 中,对于容器类型键(List、Hash、Set、ZSet),仅包含最多元素的键
    可用。但是,如果一个键有多个元素,则不一定意味着。我们需要根据业务情况进一步评估内存使用情况。
  • 第二种:rdb_bigkeys工具,编写的工具,去分析‶
  • 文件,找到 文件中的bigkeys,直接导出到文件csv方便查看。我个人推荐使用这个工具来查找大钥匙。
  • 硬件地址:https://github.com/weiyanwei412/rdb_bigkeys

    bigkey的问题有什么好的解决办法吗?

    • 避免bigkey(强烈推荐)
      • 导致redis阻塞
      • 网络流量超时❀s后,就会被删除,如果不是Redis使用4.0的 异步删除过期(lazyfree-lazy-expire yes),有阻塞Redis的可能。
    • Redis4.0 或更高版本,请使用命令 UNLINK‷ 而不是‷ ,该命令可以从内存中释放 core ​​操作在后台线程中执行,减少对Redis的影响;
    • Redis4.0或更高,可以启用没有lazy
    bit位级别操作:GETRANGE, SETRANGE, GETBIT and SETBIT
    
    byte字节级别操作:GETRANGE and SETRANGE
    
    • lazyfree-lazy-user-del = yes
    ),执行命令时DEL
    ,会释放的内存,并在后台线程中执行。

    bigkey 很多情况下,仍然会存在性能问题。例如,bigkey在分片集群模式下,移动数据会影响性能、、数据利用、 ,会影响性能。bigkey的影响。

    集中过期

    如果你发现经常使用Redis,并没有太大的延迟,但有时候突然有一波延迟。如下:延迟时间很正常,每个间隔都会有延迟波。如果出现这种情况,需要检查业务代码中是否存在多个key中心过期文件。如果多个key同时过期,此时进入Redis时,延迟可能会比较大。

    Redis 对于过期键有三种清理策略:

    被动删除:当读/写过期键时,会触发被动删除策略,键❀❀过期; 主动删除:由于惰性删除策略无法保证及时删除,Redis会定期删除key‷,‾过期。 内部 维持预定的工作。默认情况下,每100毫秒,20会从全局过期表中随机移除,过期的将被删除。

  • key
  • ,如果key

    大于,则不断重复此过程,直到键按下至 25% 或更低,或者在退出循环之前执行此操作需要 25 毫秒。 ** 这个废弃的key调度操作是在Redis线程中执行的。 **当当前使用内存

    超过限制maxmemory时,触发内存消除策略。

    也就是说,如果在主动过期过程中需要移除多个过期的key,那么在访问Redis时,应用程序必须等待过期操作完成。。只有 Redis 可以满足此客户端请求。 bigkey此时应该已经过期删除了,所以需要很长时间。此外,本次活动的迟到订单将不会记录在慢日志中。 Slow log中没有耗时的命令,但我们的应用程序意识到延迟变得更大。事实上,删除key所花费的时间已经过时了,我们需要特别注意这种情况。更多学习Redis的文章请参见:NoSQL数据库中的Redis系列。该系列定期更新。

    解决方案
    • 集中过期时间key添加随机过期时间,削减中间过期时间,减少
      • 清除过期时间key 点击;
      • Redis4.0或更高,可以启用机制,无需lazy

        当key过期时被删除s 松开按钮即可执行操作memory 在后台线程中进行,以免阻塞主线程。

      Atendra 达到最大内存限制,但是当 redis 在新数据有时间之前达到 maxmemory redis 必须从实例中逐出部分数据在写入新数据之前,将整个实例的内存保持在maxmemory以下。 ? -random

    :随机删除密钥,无论哪个密钥即将过期。
  • 易失性随机:仅随机删除过期时间的密钥。
  • allkeys-ttl:是否设置了 key 并不重要。过期,删除过期的密钥
  • noeviction:没有可以撤销的密钥。当示例内存达到maxmeory时,写入新数据会直接返回错误
  • allkeys-lfu:无论设置什么key都已过期,移除访问频率最低的key(4.0+版本支持)
  • volatile-lfu:只需移除访问频率最低的key,并设置过期时间即可(4.0+版本支持)
  • Redis 数据删除逻辑与删除过期数据相同键

    。它也是在命令执行之前执行的。也就是说,它会增加我们的Redis的延迟。此外,输入 OPS 越高,延迟越明显。示例 Redis 存储了 bigkey,因此取消和删除 ” 需要很长时间。
    建议改进:

    • 不存储bigkey,减少内存释放耗时;
    • 淘汰策略改为随机淘汰,随机淘汰率LRU更快(根据工厂情况调整);
    • 分享例子,分享很多情况下key的取消压力;
    • 如果您使用的是Redis 4.0或更高版本,启用layz-free机制,以便按键驱逐和内存释放操作在后台线程中执行(配置lazyfree-lazy-eviction = yes);

    持久化/配置影响

    Fork 需要大量时间

    操作 Redis

  • Redis背景

    RDB和AOF重复写入 期间,您需要进行调查。在此期间可能会导致经济衰退。当Redis开放其起源rdbaof rewrite时,在执行过程中,它们都需要自己的进程来创建数据持久化的方法。主进程创建子进程时,会调用操作系统提供的fork。在fork执行过程中,主进程需要将其内存页表复制给子进程。如果这个案例很大,这个复制过程也会花费更多的时间。而这个fork会消耗资源CPU。在完成fork之前,Redis将被阻塞,无论客户端请求如何都无法处理。如果现在CPU的资源已经很紧张的话,fork会花费更长的时间,即使达到第二级,这确实会影响Redis的性能。

    可以在Redis上运行命令INFO,看到k_c单位,单位是微秒。
    民工哥死磕Redis教程(二十 ):性能优化与问题排查数据的持久化会生成RDB 另外,当主从节点建立第一个数据同步时,Master也会创建第一个节点。 RDB

  • 并发送到 A 完整配置 从节点完成。因此,这一步会影响Redis上的性能。

    优化
    • 控制Redis实例的内存:尝试以下的时间fork与实例大小有关..推荐在非周末期间以及对数据丢失不敏感的公司进行备份。 (例如使用Redis作为纯缓存),您可以禁用AOF和AOF写入
    • Redis不要把实例放在虚拟机中:fork连接到系统也需要时间,♷比物理机本体需要更多
  • 虚拟机。
  • 降低主从库全同步的可能性:适当增大·repl-backlog-size参数,防止主从库全同步。
  • 发布主页

    主页是什么?

    我们都知道,当应用程序向操作系统请求内存时,会申请内存页,内存页的正常大小为4KB

    Linux2.6.38开始,内核支持

    ,内核支持 2.6.38。2MB大小以单位为单位,向操作系统请求内存。应用程序在操作系统上使用的单位变得更大,但这也意味着请求内存所需的时间增加。主进程fork子进程后,当前主进程仍然可以接收写入请求,传入的写入请求将使用Copy On Write()数据。一旦主进程有数据需要修改,Redis不会直接修改内存中已有的数据。相反,它会先复制内存数据,然后修改新内存中的数据。您还可以获得写时复制,这意味着需要先复制需要写入的内容,然后再更改。

    注意,当主进程复制内存数据时,就可以申请新的内存了。如果现在正在运行Memory Huge Pages,在此期间,即使更改了10B,‿,‿,‿,‿,‿,‿的数据, Re 也适用于组件 2MB 请求内存时的操作系统, 请求内存需要更长的时间 ,这会导致每次请求结束。 Redis 性能。如果此写入请求在bigkey上有效,则在复制此bigkey时,内存将应用于内存。 ,时间会更长。 bigkey 似乎再次影响了这里的性能。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。
    民工哥死磕Redis教程(二十 ):性能优化与问题排查

    应用 AOF

    • AOF 配置始终为 appendfsync‾ Redis 每次发生写操作时,都会将其写入磁盘。还是那句话,整个过程都是在主线程中执行的,这个过程肯定会增加Redis的写入负载。
    • aof被制作为appendfsync noredis
    • redis❀单独写。由操作系统决定何时将数据从内存刷新到磁盘。 ,Redis对性能的影响很小,但是当Redis时,由于数据保护,部分数据会丢失。当 –♿ 断开连接时,
    • AOF 设置为 appendfsync everysec –♿ ‶ AOF 当文件已满时,如果 则磁盘负载为 IT 很高,所以后台线程在做flash操作时会被阻塞(fsync系统通道)。这时候主线程仍然会收到写请求,然后主线程需要将数据写入文件内存(写调用),但是现在子线程应该处于high状态磁盘负载,导致fsync阻塞并且长时间无法恢复。当主线程执行系统调用时,也会被阻塞,直到后台线程fsyncPrint‾‾最后主执行‾才能返回安全。

    民工哥死磕Redis教程(二十 ):性能优化与问题排查我总结了以下几种情况,大家可以参考排查:

    • 子进程执行AOF重写,会占用大量IO磁盘资源;
    • 还有其他应用程序进行大量编写。

    RedisAOF后台子线程刷操作打到子进程AA

  • Redis提供确认元素。当子进程处于AOF重写时,无法进行磁盘刷新())

    这个和临时安装一样appendfsync 无在

  • 期间,配置为:
    # AOF rewrite 期间,AOF 后台子线程不进行刷盘操作
    # 相当于在这期间,临时把 appendfsync 设置为了 none
    no-appendfsync-on-rewrite yes
    

    发送到在AOF重写

    期间,如果实例宕机,很多现在数据将丢失,性能和数据安全,您需要权衡各种选择。

    碎片整理数据

  • Redis存储在内存中。当我们的应用程序频繁更改 Redis 中的数据时,可能会导致 Redis 产生内存碎片。内存分区会减少Redis的内存占用。我们可以通过执行命令 INFO 来获取本例中内存分配的比例: 民工哥死磕Redis教程(二十 ):性能优化与问题排查used_memory 表示 ❀ used_memory_rss

    表示提供的大小由操作系统传递给进程Redis
    mem_fragmentation_ratio> 1.5,说明内存碎片率超过❿**50%**。现在我们需要采取措施减少内存碎片。
    解决方法如下:
    • 如果您使用的是Redis 4.0或以下版本,可以通过重启示例来解决Redis 4.0版本,它恰好提供了自动碎片整理功能。可以通过配置启用自动碎片整理。然而,启用内存碎片整理也会导致Redis

    原因是Redis的碎片整理操作也是在主线程中完成的。当它损坏时,就要消耗CPU资源,导致消耗更多。时间,从而影响顾客的需求。

    其他原因

    • 频繁的短连接:您的业务应用程序应该使用长连接来运行Redis,以避免频繁的短连接。
    • 其他程序争夺资源:其他程序占用CPU、内存和磁盘资源,留给Redis的资源不足。

    总结

    大家应该也注意到了,性能问题Redis包含的知识点非常广泛,几乎涵盖了和内存、和 。 无论如何,同时需要了解计算机系统和操作系统的各个系统。

    考虑到资源使用,知识概念如下:

    • CPU
    • 与CPU相关
    • 内存相关:申请与释放大内存、过期、数据删除、碎片整理、大内存页、写时复制内存与内存密切相关
    • 磁盘
  • 延迟化、AOF磁盘扫描策略,也会影响磁盘
  • 网络相关:短期连接,例如流量太大,网络流量太大,降低性能 Redis
  • 计算机
  • Sy CPU结构和内存分配是计算机系统最基本的知识
  • 操作系统:写时复制、主内存页、交换和CPU绑定都是操作系统级别的知识
  • 一些改进的建议

    • 1。尝试使用短按键

    当然,为了简化,不要为了“知道按键的名称和含义”而这样做。有些值还可以简化,比如性别用0和1。

    • 2。请勿使用*

    键*。此命令是阻塞的,这意味着在执行该操作时,无法在您的实例上执行其他命令。当redis底层数据很小的时候还好,但是当数据很大的时候就真的很糟糕了。所以我们应该避免使用这个命令。您可以使用 SCAN 代替。

    • 3。在将数据存储到 Redis 之前摄取数据 Redis 会针对不同情况自动调整适当的过滤方法。
      • 4。设置有效期

      应尽可能使用有效期。比如临时数据(短信验证码)过期了,Redis会自动帮你删除!

      • 5。选择回滚策略(maxmemory策略)

      当Redis实例空间满时,会尝试轮换一些key。根据您的使用情况,强烈建议使用 volatile-lru(默认)策略 - 如果您为密钥设置了时间限制。但如果你运行的是类似于缓存的东西,并且没有为key设置停止机制,你可以考虑使用allkeys-lru机制。参见详细解释。 maxmemory-samples 3 表示每次删除时,将随机选择 3 个键,并删除最不常用的键(默认选项)。

      maxmemory-policy 六种方式 :
      volatile-lru   #只对设置了过期时间的key进行LRU(默认值)
      allkeys-lru    #是从所有key里 删除 不经常使用的key
      volatile-random #随机删除即将过期key
      allkeys-random #随机删除
      volatile-ttl   #删除即将过期的
      noeviction  #永不过期,返回错误
      
      • 6。使用位级操作和字节级操作来减少不必要的内存使用
      bit位级别操作:GETRANGE, SETRANGE, GETBIT and SETBIT
      
      byte字节级别操作:GETRANGE and SETRANGE
      
      • 7。尽可能使用哈希存储
      • 8。当业务情况不需要数据持久化时,关闭所有持久化方法可以达到最佳性能。坚持不懈/成功。
    • 9.当您想一次添加多个零件时,可以使用通道
    • 10。限制redis内存大小(64位系统不限制内存,32位系统默认最多使用3GB内存)

    如果redis数据量意外且内存有限,请尝试限制redis内存的使用size,这样可以防止redis使用交换分区或者OOM错误。 (使用交换分区,性能较低,如果内存有限,达到指定内存时无法添加数据,否则会报OOM错误。可以设置maxmemory-policy,内存不够的时候删除数据)

    • 11。 SLOWLOG [get/reset/len]
    slowlog-log-slower-than #它决定要对执行时间大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的命令进行记录。
    slowlog-max-len #它决定 slowlog 最多能保存多少条日志,当发现redis性能下降的时候可以查看下是哪些命令导致的。
    
    来源:https://blog.csdn.net/weixin_42128977/article/details/127622146

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门