5.5 redis.conf 配置详解
我是 Redis, 当程序员用指令 这个文件很重要,就好像是你们的 DNA,它能控制我的运行情况,不同的配置会有不同的特性和人生,它掌握我的人生命运,控制着我如何完成高可用、高性能。合理的配置能让我更快、更省内存,并发挥我最大的优势让我更安全运行。 以下这些配置大家必知必会,需要大家掌握每个配置背后的技术原理,学会融合贯通并在生产中正确配置,解决问题。避免出现技术悬浮,原理说的叭叭叭,配置像个大傻瓜。 本文配置文件版本是 Redis 7.0。 5.5.1 常规通用配置这些是我的常规配置,每个 Redis 启动必备参数,你一定要掌握,涉及到网络、模块插件、运行模式、日志等。 MODULES这个配置可以加载模块插件增强我的功能,常见的模块有 RedisSearch、RedisBloom 等。关于模块加载可以参考【5.6 布隆过滤器原理与实战】章节集成布隆过滤器便是通过以下配置实现加载布隆过滤器插件。
NETWORK这部分都是与网络相关的配置,很重要滴,配置不当将会有安全和性能问题。 bind
每台机器可能有多个网卡,每个网卡都有一个 IP 地址。配置了 bind,则表示我只允许来自本机指定网卡的 Redis 请求。
非也,** 注意,这个配置指的并不是只有 bind 指定的 IP 地址的计算机才能访问我。** 如果想限制指定的主机连接我,只能通过防火墙来控制,bind 参数不也能起到这个作用。 举个例子:如果我所在的服务器有两个网卡,每个网卡有一个 IP 地址, IP1,IP2。
配置
我的默认配置是 protected-mode
默认开启保护模式,如果没有设置密码或者没有 bind 配置,我只允许在本机连接我,其它机器无法连接。 如果想让其它机器连接我,有以下三种方式。
bind、protected-mode、requirepass 之间的关系
如果参数设置为
在生产环境中,为了安全,不要关闭 protected-mode,并设置 port 6379用于指定我监听的客户端 socket 端口号,默认 6379。设置为 0 则不会监听 TCP 连接,我想没人设置为 0 吧。 tcp-backlog 511
用于在
是的,我的默认配置是 511,这个配置的值不能大于 Linux 系统定义的 /proc/sys/net/core/somaxconn 值,Linux 默认的是 128。
所以我在启动的时候你会看到这样的警告: 当系统并发量大并且客户端速度缓慢的时候,在高并发系统中,需要设置一个较高的值来避免客户端连接速度慢的问题。 需要分别调整 Linux 和 Redis 的配置。
建议修改为 2048 或者更大,Linux 则在
码哥使用 macOS 系统,使用 timeout
注意事项
tcp-keepalive
用途
用于客户端与服务端的长连接,如果设置为非 0,则使用 常规配置
这些都是我的常规配置,比较通用,你必须了解。你可以把这些配置写到一个特有文件中,其他节点可以使用 daemonize
配置
你也可以配置 loglevel
指定我在运行时的日志记录级别。默认是
logfile
指定日志文件目录,默认是 需要注意的是,如果使用标准控制台输出,并且使用守护进程的模式运行,日志会发送到 /dev/null。 databases
设置数据库数量,我的默认配置是 5.5.2 RDB 快照持久化
RDB 快照持久化相关的配置,必须掌握,合理配置能我实现宕机快速恢复实现高可用。 save
使用
不关心是否丢失数据,你也可以通过配置 默认情况的我会按照如下规则来保存 RDB 内存快照。
也可以通过 stop-writes-on-bgsave-error
默认配置为 我通过这种强硬的方式来告知程序员数据持久化不正常了,否则可能没人知道 RDB 快照持久化出问题了。
当 rdbcompression
我的默认配置是
如果你不想损失因为压缩 RDB 内存快照文件的 CPU 资源,那就设置成 rdbchecksum
默认配置是 关闭了这个功能, RDB 内存快照文件的校验就是 0 ,代码会自动跳过检查。 推荐你关闭,让我快到令人发指。
你还可以通过 rdb-del-sync-files
默认配置是 dir
我的工作目录,注意这是目录而不是文件, 默认配置是 5.5.3 主从复制这部分配置很重要,涉及到主从复制的方方面面,是高可用的基石,重点对待啊伙计们。 replicaof
主从复制,使用
有以下几点需要注意。
masterauth
如果当前节点是 slave,且 master 节点配置了
配置方式为 masteruser
在 6.0 以上版本,如果使用了我的 ACL 安全功能,只配置
这时候,最好配置一个专门用于主从复制的特殊用户,配置方式为 replica-serve-stale-data
slave 节点可以有以下两种行为来决定是否处理客户端请求。
我的默认配置是 replica-read-only
这个配置用于控制 slave 实例能否接收写指令,在 2.6 版本后默认配置为 我建议保持默认配置,让 slave 节点只作为副本实现高可用。想要提高写性能,使用集群模式横向拓展更好。 repl-diskless-sync主从复制过程中,新加入的 slave 节点和 slave 节点重连后无法进行增量同步,需要进行一次全量同步,master 节点会生成 RDB 内存快照文件传输给 slave 节点。 所以这个配置是用于控制传输方式的,传输方式有两种。
使用磁盘备份的方式,master 保存在磁盘的 RDB 内存快照文件可以让多个 slave 复用。
使用无盘备份的话,当 RDB 内存快照文件传输开始,如果当前有多个
** 默认的配置是 repl-diskless-sync-delay使用无盘复制的话,如果此刻有新的 slave 发起全量同步,需要等待之前的传输完毕才能开启传输。
所以可以使用配置 因为一旦开始传输,master 节点无法响应新的 slave 节点的全量复制请求,只能在队列中等待下一次 RDB 内存快照传输。 想要关闭这个功能,设置为 0 即可。 repl-diskless-loadmastar 节点有两种方式传输 RDB,slave 节点也有两种方式加载 master 传输过来的 RDB 数据。
一共有三个取值可配置。
需要注意的是,diskless-load 目前在实验阶段,因为 RDB 内存快照数据并没有持久化到磁盘,因此有可能造成数据丢失; 另外,该模式会占用更多内存,可能会导致 OOM。 repl-ping-replica-period
默认配置 repl-timeout
很重要的一个参数,slave 与 master 之间的复制超时时间,默认配置是 超时包含以下三种情况。
当检测到超时,将会关闭 master 与 slave 之间的连接,slave 会发起重新建立主从连接的请求,对于内存数据比较大的系统,可以增大
你需要注意的是,这个配置一定要大于 repl-disable-tcp-nodelay
当 slave 与 master 全量同步(slave 发送 psync/sync 指令给 master)完成后,后续的增量同步是否设置成
如果设置成
默认配置 repl-backlog-size设置主从复制积压缓冲区(backlog) 容量大小,这是一个环形数组,正常主从同步不涉及到 repl-backlog。当主从断开重连,repl-backlog 的作用就出来了。 缓冲区用于存放断连期间 master 接受的写请求数据,当主从断开重连,通常不需要执行全量同步,只需要将断连期间的部分数据传递到 slave 即可。 主从复制积压缓冲区越大,slave 可以承受的断连时间越长。
默认配置是 repl-backlog-ttl
用于配置当 master 与 slave 断连多少秒之后,master 清空主从复制积压缓冲区(repl-backlog)。配置成 0 ,表示永远不清空。默认配置 replica-priorityslave 优先级,这个配置是给哨兵使用的,当 master 节点挂掉,哨兵会选择一个 priority 最小的 slave 节点作为新的 master,这个值越小没接越优先选中。
如果是 0,那意味着这个 slave 将不能选中成为 master,默认配置是 min-slaves-to-write 和 min-slaves-max-lag这两个配置要一起设置才有意义,如果有一个配置成 0,表示关闭该特性。 先看默认配置含义。
如果 master 发现超过 3 个 slave 节点连接 master 延迟大于 10 秒,那么 master 就停止接收客户端写请求。这么做的目的是为了尽可能保证主从数据一致性。 master 会记录每个 slave 最近一次发来 ping 的时间,掌握每个 slave 的运行情况。 tracking-table-max-keys我在 Redis 6.0 版本,实现了服务端辅助实现客户端缓存的特性,需要追踪客户端有哪些 key。当某个 key 被修改,我需要把这个失效信息发送到对应的客户端将本地缓存失效,这个配置就是用于指定追踪表保存的最大 key 数量,一旦超过这个数量,即使这个 key 没有被修改,为了回收内存我也会强制这个 key 所在的客户端缓存值失效。 设置 0 表示不限制,需要注意的是,如果使用广播模式实现键追踪,则不需要额外内存,忽略这个配置。 使用广播模式的不足就是与这个 key 无关的客户端也会收到失效消息。 5.5.4 安全正是由于我快的一塌糊涂,攻击者一秒钟可以尝试 100 万个密码,所以你应该使用非常健壮的密码。 ACL
ACL 日志的最大长度,默认配置
另外,使用 requirepass
当前 Redis 服务器的访问密码,默认是不需要密码访问,网络危险,必须设置,如 maxclients
设置客户端同时连接的最大数量,默认设置是 5.5.5 内存管理作为用内存保存数据的我,这部分的配置也相当重要。 maxmemory设置使用内存最大字节,当内存达到限制,我将尝试根据配置的内存淘汰策略(参见 maxmemory-policy)删除一些 key。建议你不要设置太大的内存,防止执行 RDB 内存快照文件或者 AOF 重写的时候因数据太大而阻塞过长时间。
推荐最大设置为
如果淘汰策略是 如果你把我当做一个 LRU 或 LFU 缓存系统的时候,那请用心关注以下配置。 maxmemory-policy
设置内存淘汰策略,定义当内存满时如何淘汰 key,默认配置是
maxmemory-samplesLRU, LFU and minimal TTL algorithms 不是精确的算法,是一个近似的算法 (主要为了节省内存)。 所以需要你自己权衡速度和精确度。默认会抽取 5 个 key,选择一个最近最少使用的 key 淘汰,你可以改变这个数量。 默认的 5 可以提供不错的结果。配置 10 会非常接近真实的 LRU 但是会耗费更多的 CPU,配置 3 会更快,但是就不那么精确了。 replica-ignore-maxmemory
从 Redis 5.0 开始,默认情况下 slave 节点会忽略
默认配置 active-expire-effort我有两种方式删除过期数据。
这个配置用于指定过期 key 滞留在内存中的比例,默认值是 1,表示最多只能有 10 % 的过期 key 驻留在内存中,值设置的越小,那么一次淘汰周期内需需要消耗的 CPU 将会更多,因为需要删除更多的过期数据。 5.5.6 惰性释放
我提供了两种删除 key 的基本命令用于删除数据。
lazyfree-lazy-eviction
由于 maxmemory 和 maxmemory-policy 策略配置,我会删除一些数据,防止内存爆掉。使用 lazyfree-lazy-expire
对于设置了 TTL 的键,过期后删除。如果想启用 lazy free 机制删除,则配置 lazyfree-lazy-server-del针对有些指令在处理已存在的键时,会带有一个隐式的 DEL 键的操作。
如 replica-lazy-flush
该配置针对 slave 进行全量数据同步,在加载 master 的 RDB 内存快照文件之前,会先运行
推荐你使用 lazyfree-lazy-user-del
意思是是否将 lazyfree-lazy-user-flush
IO 多线程
大家知道我是单线程模型处理读写请求,但是有一些操作可以使用其他线程处理,比如 在 6.0 版本,我提供了 I/O 多线程处理 Socket 读写,利用 I/O 多线程可以提高客户端 Socket 读写性能。 默认配置是关闭的,我只建议当你的机器至少是 4 核 CPU 或者更多的情况启用,并且配置的线程数少于机器总 CPU 核数,配置超过 8 个线程对提升没什么帮助。 当你的机器是四核 CPU,那可以尝试配置使用 2~3 个 I/O 线程,如果是 8 核 CPU,一般只需要配置 6 个线程。 如下配置表示开启 I/O 线程组,线程组的 I/O 线程数量为 3。
5.5.7 AOF 持久化除了 RDB 内存快照文件作为持久化手段以外,还能使用 AOF (Append only file) 实现持久化,AOF 是一种可选的持久化策略提供更好数据安全性。 默认配置下,我最多只会丢失一秒的数据,你甚至可以配置更高级别,最多只丢失一次 write 操作,但这样会对损耗性能。 appendonly
appendfilename
指定 AOF 文件名称,默认名字是 appendfsync
调用操作系统的
默认配置是 no-appendfsync-on-rewrite
当 appendfsync 的配置设置成
为了缓解这个问题,可以使用以下配置 这样的话,就会出现当前有子进程在做 bgsave 或者其他的磁盘操作时,我就无法继续写 AOF 文件,这意味着可能会丢失更多数据。
如果有延迟问题,请将此选项改为 AOF 重写为了防止 AOF 文件过大,antirez 大佬给我搞了个 AOF 重写机制。
除了这个配置,你还要配置 如果该 AOF 文件大小小于该值,即使文件增长比例达到 100%,我也不会触发 AOF 重写操作,这是为了防止 AOF 文件其实很小,但是满足增长百分比时的多余 AOF 重写操作。
如果配置为 aof-load-truncated
加载 AOF 文件把数据还原到内存中,文件可能是损坏的,比如文件末尾是错误的。这种情况一般是由于宕机导致,尤其是使用 ext4 文件系统挂载时没配置 在这种情况下,我可以直接报错,或者尽可能的读取可读的 AOF 内容。
如果配置成
配置成 aof-use-rdb-preamble
这就是大名鼎鼎的 RDB-AOF 混合持久化功能,配置成 混合持久化是在 AOF 重写完成的,开启混合持久化后,fork 出的子进程先将内存数据以 RDB 的方式写入 AOF 文件,接着把 RDB 格式数据写入 AOF 文件期间收到的增量命令从重写缓冲区以 AOF 格式写到文件中。 写入完成后通知主进程更新统计信息,并把含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的 AOF 文件。 这样的好处是可以结合 RDB 和 AOF 的优点,实现快速加载同时避免丢失过多数据,缺点是 AOF 文件的 RDB 部分内容不是 AOF 格式,可读性差(都是程序解析读取,哪个傻瓜程序员去读这个呀),强烈推荐你使用这个来保证持久化。 aof-timestamp-enabled我在 7.0 版本新增的特性,大体就是讲 AOF 现在支持时间戳了,你可以做到基于时间点来恢复数据。
默认是是 5.5.7 Cluster 集群Redis Cluster 集群相关配置,使用集群方式的你必须重视和知晓。别嘴上原理说的头头是道,而集群有哪些配置?如何配置让集群快到飞起,实现真正的高可用却一头雾水,通过下面这些配置详解也让你对集群原理更加深刻。 cluster-enabled
普通的 Redis 实例是不能成为集群的一员,想要将该节点加入 Redis Cluster,需要设置 cluster-config-file
集群中的每个节点都有一个配置文件,这个文件并不是让程序员编辑的,是我自己创建和更新的,每个节点都要使用不同的配置文件,一定要确保同一个集群中的不同节点使用的是不同的文件。 cluster-node-timeout设置集群节点不可用的最大超时时间,节点失效检测。集群中当一个节点向另一个节点发送 PING 命令,但是目标节点未在给定的时限内返回 PING 命令的回复时,那么发送命令的节点会将目标节点标记为 PFAIL (possible failuer,可能已失效); 如果 master 节点超过这个时间还是无响应,则用它的从节点将启动故障迁移,升级成主节点。
默认配置是 cluster-port
该端口是集群总线监听 TCP 连接的端口,默认配置为
cluster-replica-validity-factor该配置用于决定当 Redis Cluster 集群中,一个 master 宕机后,如何选择一个 slave 节点完成故障转移自动恢复(failover)。如果设置为 0 ,则不管 slave 与 master 之间断开多久,都有资格成为 master。 下面提供了两种方式来评估 slave 的数据是否太旧。
针对第二点,交互时间可以通过配置定义,如果 slave 与 master 上次交互的时间大于
例如,``node-timeout = 30
调大
考虑高可用,建议大家设置为 cluster-migration-barrier没有 slave 节点的 master 节点称为孤儿 master 节点,这个配置就是用于防止出现孤儿 master。 当某个 master 的 slave 节点宕机后,集群会从其他 master 中选出一个富余的 slave 节点迁移过来,确保每个 master 节点至少有一个 slave 节点,防止当孤立 master 节点宕机时,没有 slave 节点可以升为 master 导致集群不可用。
默认配置为 含义是:被迁移的 master 节点至少还有 1 个 slave 节点才能做迁移操作。比如 master A 节点有 2 个以上 slave 节点 ,当集群出现孤儿 master B 节点时,A 节点富余的 slave 节点可以迁移到 master B 节点上。
生产环境建议维持默认值,最大可能保证高可用,设置为非常大的值或者配置
cluster-require-full-coverage
默认配置是 这就会导致集群部分宕机,整个集群就不可用了,当所有哈希槽都有分配,集群会自动变为可用状态。
如果你希望 cluster 的子集依然可用,配置成 cluster-replica-no-failover
当配置成 这个配置在多数据中心的情况下会很有用,你可能希望某个数据中心永远不要升级为 master 节点,否则 master 节点就漂移到其他数据中心了,正常情况设置成 no。 cluster-allow-reads-when-down
默认是
设置成 cluster-allow-pubsubshard-when-down
配置成 cluster-link-sendbuf-limit设置每个集群总线连接的发送字节缓冲区的内存使用限制,超过限制缓冲区将被清空(主要为了防止发送缓冲区发送给慢速连接时无限延长时间的问题)。 默认禁用,建议最小设置 1gb,这样默认情况下集群连接缓冲区可以容纳至少一条 pubsub 消息(client-query-buffer-limit 默认是 1gb); 5.5.8 性能监控慢查询日志慢查询(Slow Log)日志是我用于记录慢查询执行时间的日志系统,只要查询超过配置的时间,都会记录。slowlog 只保存在内存中,因此效率很高,大家不用担心会影响到 Redis 的性能。 执行时间不包括 I/O 操作的时间,比如与客户端建立连接、发送回复等,只记录执行命令执行阶段所需要的时间。 你可以使用两个参数配置慢查询日志系统。
延迟监控延迟监控(LATENCY MONITOR)系统会在运行时抽样部分命令来帮助你分析 Redis 卡顿的原因。
通过
默认配置
在运行过程中你怀疑有延迟性能问题,想要监控的话可以使用 5.5.9 高级设置这部分配置主要围绕以下几个方面。
Hashes(散列表)在 Redis 7.0 版本散列表数据类型有两种数据结构保存数据,分别为散列表和 listpack。当数据量很小时,可以使用更高效的数据结构存储,从而达到在不影响性能的情况下节省内存。
在 7.0 版本以前,使用的是 ziplist 数据结构,配置如下。
Lists(列表)Lists 也可以使用一种特殊方式进行编码来节省大量内存空间。在 Redis 7.0 之后,Lits 底层的数据结构使用 linkedlist 或者 listpack 。 Redis 3.2 版本,List 内部是通过 linkedlist 和 quicklist 实现,quicklist 是一个双向链表, quicklist 的每个节点都是一个 ziplist,从而实现节省内存。 元素少时用 quicklist,元素多时用 linkedlist。listpack 的目的就是用于替代 ziplist 和 quicklist。listpack 也叫紧凑列表,它的特点就是用一块连续的内存空间来紧凑地保存数据,同时为了节省内存空间 list-max-ziplist-size
7.0 版本之前
当
默认值为 -2,也是官方最推荐的值,当然你可以根据自己的实际情况进行修改。 list-max-listpack-size
7.0 之后,配置修改为 list-compress-depth
压缩深度配置,用来配置压缩 Lists 的,当 Lists 底层使用 linkedlist 也是可以压缩的,默认是 不同参数值的含义如下。
需要注意的是,head 和 tail 节点永远都不会被压缩。 Sets(无序集合)Sets 底层的数据结构可以是 intset(整形数组)和 Hashtable(散列表),intset 你可以理解成数组,Hashtable 就是普通的散列表(key 存的是 Sets 的值,value 为 null)。有没有觉得 Sets 使用散列表存储是意想不到的事情? set-max-intset-entries
当集合的元素都是 64 位以内的十进制整数时且长度不超过 SortedSets(有序集合)在 Redis 7.0 版本之前,有序集合底层的数据结构有 ziplist 和 skipist,之后使用 listpack 代替了 ziplist。
7.0 版本之前,当集合元素个数小于
HyperLogLogHyperLogLog 是一种高级数据结构,统计基数的利器。HyperLogLog 的存储结构分为密集存储结构和稀疏存储结构两种,默认为稀疏存储结构,而我们常说的占用 12K 内存的则是密集存储结构,稀疏结构占用的内存会更小。 hll-sparse-max-bytes
默认配置是 如果 HyperLogLog 存储内容大小大于 hll-sparse-max-bytes 配置的值将会转换成稠密的数据结构(dense)。
推荐的值是 0~3000,这样 Streams(流)Stream 是 Redis 5.0 版本新增的数据类型。Redis Streams 是一些由基数树(Radix Tree)连接在一起的节点经过 delta 压缩后构成的,这些节点与 Stream 中的消息条目(Stream Entry)并非一一对应,而是每个节点中都存储着若干 Stream 条目,因此这些节点也被称为宏节点或大节点。 stream-node-max-bytes 4096 单位为 Byte,默认值 4096,用于设定每个宏节点占用的内存上限为 4096,0 表示无限制。 stream-node-max-entries 100 用于设定每个宏节点存储元素个数。 默认值 100,0 表示无限制。当一个宏节点存储的 Stream 条目到达上限,新添加的条目会存储到新的宏节点中。 rehash我采用的是渐进式 rehash,这是一个惰性策略,不会一次性把所有数据迁移完,而是分散到每次请求中,这样做的目的是防止数据太多要迁移阻塞主线程。
在渐进式 rehash 的同时,推荐你使用 关闭该功能的话,如果这些 key 不再活跃不被被访问到,rehash 操作可能不再有机会完成,会导致散列表占用更多内存。 客户端输出缓冲区限制这三个配置是用来强制断开客户端连接的,当客户端没有及时把缓冲区的数据读取完毕,我会认为这个客户端可能完蛋了(一个常见的原因是 Pub/Sub 客户端处理发布者的消息不够快),于是断开连接。 一共分为三种不同类型的客户端,分别设置不同的限制。
<class> 表示不同类型的客户端,当客户端的缓冲区内容大小达到 <hard limit > 后我就立马断开与这个客户端的连接,或者达到 <soft limit> 并持续了 <soft seconds > 秒后断开。 默认情况下,普通客户端不会限制,只有后异步的客户端才可能发送发送请求的速度比读取响应速度快的问题。比如 pubsub 和 replica 客户端会有默认的限制。 soft limit 或者 hard limit 设置为 0,表示不启用此限制。默认配置如下。
client-query-buffer-limit每个客户端都有一个 query buffer(查询缓冲区或输入缓冲区),用于保存客户端发送命令,Redis Server 从 query buffer 获取命令并执行。 如果程序的 Key 设计不合理,客户端使用大量的 query buffer,导致 Redis 很容易达到 maxmeory 限制。最好限制在一个固定的大小来避免占用过大内存的问题。 如果你需要发送巨大的 multi/exec 请求的时候,那可以适当修改这个值以满足你的特殊需求。
默认配置为 maxmemory-clients这是 7.0 版本特性,每个与服务端建立连接的客户端都会占用内存(查询缓冲区、输出缓冲区和其他缓冲区),大量的客户端可能会占用过大内存导致 OOM,为了避免这个情况,我提供了一种叫做(Client Eviction)客户端驱逐机制用于限制内存占用。 配置方式有两种。
默认配置是
不是的,一旦达到限制,我会优先尝试断开使用内存最多的客户端。 proto-max-bulk-len
批量请求(单个字符串的元素)内存大小限制,默认是 hz我会在后台调用一些函数来执行很多后台任务,比如关闭超时连接,清理不再被请求的过期的 key,rehash、执行 RDB 内存快照和 AOF 持久化等。 并不是所有的后台任务都需要使用相同的频率来执行,你可以使用 hz 参数来决定执行这些任务的频率。
默认配置是 这个值的范围是 1~500,不过并不推荐设置大于 100 的值。大家使用默认值就好,或者最多调高到 100。 dynamic-hz
默认配置是
|
0 | 104 | 255 | 255 | 255 | 255 |
1 | 18 | 49 | 255 | 255 | 255 |
10 | 10 | 18 | 142 | 255 | 255 |
100 | 8 | 11 | 49 | 143 | 255 |
factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits |
---|
lfu-decay-time 用于调整 Logistic Counter 的衰减速度,它是一个以分钟为单位的数值,默认值为 1;lfu-decay-time 值越大,衰减越慢。
5.5.9 在线内存碎片整理
MySQL:“什么是在线内存碎片整理?”
Active (online) defragmentation 在线内存碎片整理指的是自动压缩内存分配器分配和 Redis 频繁做更新操作、大量过期数据删除,释放的空间(不够连续)无法得到复用的内存空间。
通常来说当碎片化达到一定程度(查看下面的配置)Redis 会使用 Jemalloc 的特性创建连续的内存空间, 并在此内存空间对现有的值进行拷贝,拷贝完成后会释放掉旧的数据。 这个过程会对所有的导致碎片化的 key 以增量的形式进行。
需要注意的是
- 这个功能默认是关闭的,并且只有在编译 Redis 时使用我们代码中的 Jemalloc 版本才生效。(这是 Linux 下的默认行为)。
- 在实际使用中,建议是在 Redis 服务出现较多的内存碎片时启用(内存碎片率大于 1.5),正常情况下尽量保持禁用状态。
-
如果你需要试验这项特性,可以通过命令
CONFIG SET activefrag yes
来启用。
清理的条件
activefrag yes
:内存碎片整理总开关,默认为禁用状态 no。
active-defrag-ignore-bytes 200mb
:内存碎片占用的内存达到 200MB。
active-defrag-threshold-lower 20
:内存碎片的空间占比超过系统分配给 Redis 空间的 20% 。
在同时满足上面三项配置时,内存碎片自动整理功能才会启用。
CPU 资源占用
MySQL:如何避免自动内存碎片整理对性能造成影响?
清理的条件有了,还需要分配清理碎片占用的 CPU 资源,保证既能正常清理碎片,又能避免对 Redis 处理请求的性能影响。
active-defrag-cycle-min 5
:自动清理过程中,占用 CPU 时间的比例不低于 5%,从而保证能正常展开清理任务。
active-defrag-cycle-max 20
:自动清理过程占用的 CPU 时间比例不能高于 20%,超过的话就立刻停止清理,避免对 Redis 的阻塞,造成高延迟。
整理力度
active-defrag-max-scan-fields 1000
:碎片整理扫描到 set/hash/zset/list
时,仅当 set/hash/zset/list
的长度小于此阀值时,才会将此键值对加入碎片整理,大于这个值的键值对会放在一个列表中延迟处理。
active-defrag-threshold-upper 100
:内存碎片空间占操作系统分配给 Redis 的总空间比例达此阈值(默认 100%),我会尽最大努力整理碎片。建议你调整为 80。
jemalloc-bg-thread
默认配置为 jemalloc-bg-thread yes
,表示启用清除脏页后台线程。
绑定 CPU
你可以将 Redis 的不同线程和进程绑定到特定的 CPU,减少上下文切换,提高 CPU L1、L2 Cache 命中率,实现最大化的性能。
你可以通过修改配置文件或者 taskset
命令绑定。
可分为三个模块。
- 主线程和 I/O 线程:负责命令读取、解析、结果返回。命令执行由主线程完成。
- bio 线程:负责执行耗时的异步任务,如 close fd、AOF fsync 等。
- 后台进程:fork 子进程(RDB bgsave、AOF rewrite bgrewriteaof)来执行耗时的命令。
Redis 支持分别配置上述模块的 CPU 亲合度,默认情况是关闭的。
-
server_cpulist 0-7:2
,I/O 线程(包含主线程)相关操作绑定到 CPU 0、2、4、6。 -
bio_cpulist 1,3
,bio 线程相关的操作绑定到 CPU 1、3。 -
aof_rewrite_cpulist
,aof rewrite 后台进程绑定到 CPU 8、9、10、11。 -
bgsave_cpulist 1,10-11
,bgsave 后台进程绑定到 CPU 1、10、11。
注意事项
- Linux 下,使用 「numactl --hardware」 查看硬件布局,确保支持并开启 NUMA。
- 线程要尽可能分布在 不同的 CPU,相同的 node,设置 CPU 亲和度才有效,否则会造成频繁上下文切换。
- 你要熟悉 CPU 架构,做好充分的测试。否则可能适得其反,导致 Redis 性能下降。
(责任编辑:IT)