首页 > 数据库 >Redis 性能优化

Redis 性能优化

时间:2024-01-10 16:56:10浏览次数:36  
标签:latency far Max 性能 Redis so microseconds 优化

概述

当我们操作 Redis 发现耗时较长时,原因可能有两个:

  • 服务间存在网络延迟
  • Redis 服务本身存在问题

如果是第一种情况,那么所有服务都会发生网络延迟,只需要联系运维处理即可,这里主要讨论第二种情况


Redis 基准性能测试

基准性能指 Redis 在一台负载正常的机器上的最大响应延迟和平均响应延迟,我们可以找一台同配置的机器,与原机器比较基准性能,看看 Redis 是不是真的变慢了

从 Redis 2.8.7 开始,redis-cli 命令可以追加 –intrinsic-latency 选项,用于监测和统计某个时间段内 Redis 的最大延迟

# 60 指的是测试时长为 60s,可以任意指定
redis-cli -h 127.0.0.1 -p 6379 --intrinsic-latency 60
Max latency so far: 1 microseconds.
Max latency so far: 157 microseconds.
Max latency so far: 173 microseconds.
Max latency so far: 323 microseconds.
Max latency so far: 324 microseconds.
Max latency so far: 325 microseconds.
Max latency so far: 334 microseconds.
Max latency so far: 520 microseconds.
Max latency so far: 527 microseconds.
Max latency so far: 591 microseconds.
Max latency so far: 1178 microseconds.
Max latency so far: 2299 microseconds.
Max latency so far: 2881 microseconds.
Max latency so far: 4113 microseconds.

597018388 total runs (avg latency: 0.1005 microseconds / 100.50 nanoseconds per run).
Worst run took 40926x longer than the average latency.

从输出结果可以看出 60s 内最大延迟是 4113 微秒

使用以下命令,查看 Redis 的最小、最大、平均访问延迟

``shell
redis-cli -h 127.0.0.1 -p 6379 --latency
min: 0, max: 6, avg: 0.24 (6064 samples)

按 ctrl + c 结束命令,可见平均延迟为0.24ms,共统计了 6064 个样本数据

还可以使用以下命令,查看一段时间内 Redis 的最小、最大、平均访问延迟

```shell
redis-cli -h 127.0.0.1 -p 6379 --latency-history -i 1
min: 0, max: 1, avg: 0.29 (98 samples) -- 1.01 seconds range
min: 0, max: 1, avg: 0.25 (96 samples) -- 1.00 seconds range
min: 0, max: 1, avg: 0.28 (96 samples) -- 1.00 seconds range
min: 0, max: 1, avg: 0.26 (96 samples) -- 1.00 seconds range
min: 0, max: 1, avg: 0.27 (97 samples) -- 1.00 seconds range
...

以上输出结果是,每隔 1 秒采样 Redis 的平均操作耗时,其结果分布在 0.25 ~ 0.29ms 之间

通过以上命令,我们可以在相同配置的服务器上测试比较 Redis 的基准性能,找到可能变慢了的 Redis 实例


原因分析

找到目标,接下来分析可能导致 Redis 变慢的因素

1. 使用慢日志查询耗时命令

Redis 提供了慢日志命令的统计功能,它记录了有哪些命令在执行时耗时比较久

查看 Redis 慢日志之前,你需要设置慢日志的阈值,例如,设置慢日志的阈值为 10ms,并且保留最近 128 条慢日志记录

在 redis.conf 中设置,重启 Redis 实例来生效

slowlog-log-slower-than 10000
slowlog-max-len 128

也通过 CONFIG SET 命令动态设置

CONFIG SET slowlog-log-slower-than 10000
CONFIG SET slowlog-max-len 128

执行 slowlog get 命令查询最近记录的慢日志,可以指定返回条数,不指定默认十条

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"
2) 1) (integer) 32692
    2) (integer) 1593763337
    3) (integer) 5044
    4) 1) "GET"
        2) "user_info:1000"
.....

通过查看慢日志,我们就可以知道在什么时间点,执行了哪些命令比较耗时,一般原因有以下两个:

  • 使用复杂度过高的命令,如 SORT、SUNION、ZUNIONSTORE 等聚合类命令,
  • 查询返回数据量过大

2. 操作 bigkey

如果你查询慢日志发现,并不是复杂度过高的命令导致的,而都是 SET / DEL 这种简单命令出现在慢日志中,那么你就要考虑你的实例否写入了 bigkey

Redis 在写入数据时,需要为新的数据分配内存,相对应的,当从 Redis 中删除数据时,它会释放对应的内存空间。如果一个 key 写入的 value 非常大,那么 Redis 在分配内存时就会比较耗时。同样的,当删除这个 key 时,释放内存也会比较耗时,这种类型的 key 我们一般称之为 bigkey

Redis 提供了扫描 bigkey 的命令,用于扫描一个实例 bigkey 的分布情况

redis-cli -h 127.0.0.1 -p 6379 --bigkeys

...
-------- 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)
  • 该命令使用 scan 方式对 key 进行统计,所以无需担心造成阻塞,但可能会对 Redis 实例造成一定的负担
  • 输出大概分为两部分,summary 之上的部分只是显示了扫描的过程,summary 部分给出了每种数据结构中最大的 Key
  • 统计的 bigkey 只有 string 类型是以字节长度来衡量,list、set、zset 等都是以元素个数作为衡量,不能说明其占用内存就一定多

针对 bigkey 导致延迟的问题,有两点可以优化:

  • 将 bigkey 拆分成多个小的 key,需要修改应用程序的代码
  • 使用压缩算法来减小对象的大小
  • 如果你使用的 Redis 是 4.0 以上版本,用 unlink 命令替代 del 命令异步删除
  • 如果你使用的 Redis 是 6.0 以上版本,可以开启 lazy-free 机制(lazyfree-lazy-user-del = yes),在执行 del 命令时,释放内存也会放到后台线程中执行

3. 集中过期

如果有大量的 key 在某个固定时间点集中过期,在这个时间点访问 Redis 时,就有可能导致延时变大,如果此时需要过期删除的是一个 bigkey,那么这个耗时会更久

解决办法是分散过期时间,可以为集中过期 key 增加一个随机过期时间。如果你使用的 Redis 是 4.0 以上版本,可以开启 lazy-free 机制(lazyfree-lazy-expire yes),当删除过期 key 时,把释放内存的操作放到后台线程中执行,避免阻塞主线程

4. 可用内存达到上限

Redis 可以设置最大可用内存(maxmemory),默认是实例内存。当 Redis 达到 maxmemory 时,Redis 必须清除部分数据,从而造成延迟。如果存储了 bigkey,那么耗时会更久

使用 info memory 命令查看 Redis 内存占用情况,比较 used_memory 和 maxmemory

localhost:6379> info memory
used_memory:692264  # redis 服务器分配的内存总量,也就是内部存储数据的内存占用量
used_memory_human:676.04K  # 以可读形式返回 used_memory
used_memory_rss:655336  # 从操作系统的角度返回 redis 进程占用的物理内存总量
.....
maxmemory:0  # redis 能使用的最大内存上限,0 表示没有上限
maxmemory_human:0B  # 以可读形式返回 maxmemory

可以调整 Redis 的内存淘汰策略,比如改为随机淘汰,随机淘汰速度要快很多,尽可能减少耗时。如果使用的是 Redis 4.0 以上版本,开启 layz-free 机制,把淘汰 key 释放内存的操作放到后台线程中执行(lazyfree-lazy-eviction = yes)

5. fork 耗时

当 Redis 开启了后台 RDB 和 AOF rewrite 后,需要主进程创建出一个子进程进行数据的持久化。主进程创建子进程,会调用操作系统提供的 fork 函数。而 fork 在执行过程中,主进程需要拷贝自己的内存页表给子进程,如果这个实例很大,那么这个拷贝的过程也会比较耗时

可以执行 info stats 命令获取到 latest_fork_usec 指标,表示 Redis 最近一次 fork 操作耗时,如果耗时很大,比如超过1秒,则需要做出优化调整

localhost:6379> info stats
...
latest_fork_usec:59477  # 上一次 fork 耗时,单位微秒
...

推荐在低峰期进行备份,而对于丢失数据不敏感的业务(例如把 Redis 当做纯缓存使用)可以关闭持久化

标签:latency,far,Max,性能,Redis,so,microseconds,优化
From: https://www.cnblogs.com/Yee-Q/p/17944896

相关文章

  • 无涯教程-Redis - SELECT index 命令函数
    RedisSELECT命令用于选择具有指定的从零开始的数字索引的DB,新连接始终使用DB0。SELECT-返回值返回OKSELECT-语法以下是RedisSELECT命令的基本语法。redis127.0.0.1:6379>SELECTDB_INDEXSELECT-示例redis127.0.0.1:6379>SELECT1OKredis127.0.0.1:6......
  • MoE模型性能还能更上一层楼?一次QLoRA微调实践
    Fine-Tuning Mixtral 8x7B with QLoRA:Enhancing Model Performance ......
  • Node.js 多线程编程:优化性能的关键步骤
    在 Node.js多线程允许Node.js应用并行处理任务,以此来提高性能和响应速度。Node.js内置了如 worker_threads 这样的模块来支持多线程。通过分配任务给不同的线程,能够更好地利用多核处理器,缓解单线程应用可能出现的瓶颈。Node.js中多线程的适用场景在 Node.js 中,以下几种情......
  • Helix QAC 2023.4 新版支持C++20语言,带来更多性能提升!
    HelixQAC2023.4新增功能HelixQAC2023.4全面支持MISRAC++:2023®规则,涵盖100%的指南。此版本还加强了对C++20语言的支持,改进了数据流分析性能,并在整个产品中增加了多项用户体验改进。增强的C++20支持此版本新增了对以下语言特性的支持:-模板参数列表和函数声明的requires-clau......
  • 无涯教程-Redis - QUIT 命令函数
    RedisQUIT命令要求服务器关闭连接,一旦所有待处理的回复都已写入客户端,连接即被关闭。QUIT-返回值返回OKQUIT-语法以下是RedisQUIT命令的基本语法。redis127.0.0.1:6379>QUITQUIT-示例redis127.0.0.1:6379>QUITOK参考链接https://www.learnfk.com/red......
  • Helix QAC 2023.4 新版支持C++20语言,带来更多性能提升!
    HelixQAC2023.4新增功能HelixQAC2023.4全面支持MISRAC++:2023®规则,涵盖100%的指南。此版本还加强了对C++20语言的支持,改进了数据流分析性能,并在整个产品中增加了多项用户体验改进。增强的C++20支持此版本新增了对以下语言特性的支持:-模板参数列表和函数声明的require......
  • redis for k8s
    deploy.yaml基于nfs的存储apiVersion:v1kind:ConfigMapmetadata:name:redis-cmnamespace:testdata:redis.conf:|+requirepass1314521protected-modenoport6379tcp-backlog511timeout0tcp-keepalive300daemonizeno......
  • 无涯教程-Redis - AUTH password 命令函数
    RedisAUTH命令用于使用给定的密码对服务器进行身份验证,如果密码与配置文件中的密码匹配,则服务器将以OK状态代码进行答复并开始接受命令。否则,将返回错误,并且客户端需要尝试新密码。AUTHpassword-返回值返回字符串。AUTHpassword-语法以下是RedisAUTH命令的基本语......
  • 尊嘟假嘟?三行代码提升接口性能600倍
    一、背景  业务在群里反馈编辑结算单时有些账单明细查不出来,但是新建结算单可以,我第一反应是去测试环境试试有没有该问题,结果发现没任何问题!!!  然后我登录生产环境编辑业务反馈有问题的结算单,发现查询接口直接504网关超时了,此时心里已经猜到是代码性能问题导致的,接来下就把重......
  • 使用cURL命令在Linux中测试HTTP服务器的性能
    cURL是一个强大的命令行工具,用于从或向服务器传输数据。它支持多种协议,包括HTTP、HTTPS、FTP等。在Linux系统中,cURL可以用于测试和评估HTTP服务器的性能。下面是一些使用cURL命令测试HTTP服务器性能的示例和说明。1.基本请求要向指定的URL发送基本的GET请求,你可以使用以下命令:bash......