Redis进程异常退出排查

本文详细指导如何排查Redis进程异常退出,包括内存不足、人为kill、cli命令、bug崩溃等问题,同时提供内存优化技巧,如字符串长度控制、共享对象池和编码优化等。

Redis进程异常退出排查
一、排查思路
1. 是否因为系统内存不足被oom killer杀掉;
如果是oom killer杀掉的话,一般会在/var/log/*留下日志,dmesg也应该能查到,可以使用命令搜索:

dmesg | egrep -i 'killed process'
grep oom /var/log/*
grep total_vm /var/log/*
1
2
3
如果确实是由于内存不足被oom killer杀掉,可以考虑:

加大系统内存;
修改redis.conf配置,设置合理的maxmemory,保证机器有20%~30%的闲置内存,并使用适当的回收策略;
maxmemory 512mb
maxmemory-policy volatile-lru
1
2
降低redis进程的oom adj分数;
“OOM killer会在可用内存不足时选择性的杀掉用户进程,它的运行规则是怎样的,会选择哪些用户进程“下手”呢?OOM killer进程会为每个用户进程设置一个权值,这个权值越高,被“下手”的概率就越高,反之概率越低。每个进程的权值存放在/proc/{progress_id}/oom_score中,这个值是受/proc/{progress_id}/oom_adj的控制,oom_adj在不同的Linux版本的最小值不同,可以参考Linux源码中oom.h(从-15到-17)。当oom_adj设置为最小值时,该进程将不会被OOM killer杀掉。”

设置方法如下:

echo -17 > /proc/${process_id}/oom_adj
1
优化redis的内存使用与设置;
详情参考下文的介绍以及文末的相关链接。
2. 是否被人为kill掉
如果是人为kill进程,可以搜索last和history的记录,查看是什么登陆用户在什么时间杀掉的;
如果系统有安装audit,也可以使用ausearch搜索命令记录:
ausearch -sc kill
1
3. 是否因为redis-cli发送了shutdown命令导致
如果是cli发送的shutdown命令导致redis退出,redis本身的log会有如下记录:

3803:S 11 Oct 18:12:51.251 # User requested shutdown...
3803:S 11 Oct 18:12:51.251 * Removing the pid file.
3803:S 11 Oct 18:12:51.252 # Redis is now ready to exit, bye bye...
1
2
3
如果还没打开redis log,需要在redis.conf中指定路径然后重启:

dir "/opt/redis-4.0.9/redis-cluster/7000"
1
避免进程被cli远程关闭,可以设置密码,或者在redis.conf中禁用shutdown命令来实现,我们选择采用后者:

rename-command SHUTDOWN ""
1
4. 是否redis本身的bug导致崩溃
设置系统ulimit,在进程崩溃时候生成core dump:
ulimit -c unlimited
1
修改/etc/sysctl.conf文件,加入如下配置指定core dump文件生成的名称和路径:

kernel.core_uses_pid = 1
kernel.core_pattern = /var/core/core_%e_%p
1
2
注意不同linux发行版可能设置的方式略有不同。

使用strace命令跟踪进程行为:
screen -S redis_trace_7000
strace -T -tt -e trace=all -p `ps -ef|grep redis|grep 7000|grep -v -i screen|grep -v grep|awk '{split($0,a);print a[2]}'`
1
2
然后ctrl-a d退出screen

使用gdb attach到redis进程
同样建议使用独立的screen执行gdb,另外,gdb需要使用ptrace,如果发现ptrace: Operation not permitted的报错,需要关闭其他已经使用ptrace命令的进程,例如strace命令。

gdb /usr/local/bin/redis-server 58414
(gdb) continue
1
2
使用redis-cli连上server,发送debug segfault指令可以使redis server崩溃,这时候可以:
使用bt查看栈信息

(gdb) bt
#0  debugCommand (c=0x7ffc32005000) at debug.c:220
#1  0x000000010d246d63 in call (c=0x7ffc32005000) at redis.c:1163
#2  0x000000010d247290 in processCommand (c=0x7ffc32005000) at redis.c:1305
#3  0x000000010d251660 in processInputBuffer (c=0x7ffc32005000) at networking.c:959
#4  0x000000010d251872 in readQueryFromClient (el=0x0, fd=5, privdata=0x7fff76f1c0b0, mask=220924512) at networking.c:1021
#5  0x000000010d243523 in aeProcessEvents (eventLoop=0x7fff6ce408d0, flags=220829559) at ae.c:352
#6  0x000000010d24373b in aeMain (eventLoop=0x10d429ef0) at ae.c:397
......
1
2
3
4
5
6
7
8
9
使用info registers查看寄存器信息

(gdb) info registers
rax            0x0  0
rbx            0x7ffc32005000   140721147367424
rcx            0x10d2b0a60  4515891808
rdx            0x7fff76f1c0b0   140735188943024
rsi            0x10d299777  4515796855
rdi            0x0  0
rbp            0x7fff6ce40730   0x7fff6ce40730
rsp            0x7fff6ce40650   0x7fff6ce40650
r8             0x4f26b3f7   1327936503
r9             0x7fff6ce40718   140735020271384
r10            0x81 129
......
1
2
3
4
5
6
7
8
9
10
11
12
13
最后,使用gcore产生core dump文件

(gdb) gcore
Saved corefile core.58414
1
2
二、内存使用优化
缩减键值对象
在条件允许的情况下建议字符串长度控制在39字节以内,减少创建redisObject内存分配次数;
缩减键(key)和值(value)的长度;
key长度:如在设计键时,在完整描述业务情况下,键值越短越好。
value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组放入Redis。首先应该在业务上精简业务对象,去掉不必要的属性避免存储无效数据。其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组大小。在内存紧张的情况下,可以使用通用压缩算法压缩json,xml后再存入Redis,从而降低内存占用,例如使用GZIP压缩后的json可降低约60%的空间。
共享对象池
使用共享对象池。整数对象池在Redis中通过变量REDIS_SHARED_INTEGERS定义,不能通过配置修改。可以通过object refcount 命令查看对象引用数验证是否启用整数对象池技术。使用共享对象池后,相同的数据内存使用降低30%以上。可见当数据大量使用[0-9999]的整数时,共享对象池可以节约大量内存。注意,当设置maxmemory并启用LRU相关淘汰策略如:volatile-lru,allkeys-lru时,Redis禁止使用共享对象池。
字符串优化
尽量减少字符串频繁修改操作如append,setrange, 改为直接使用set修改字符串,降低预分配带来的内存浪费和内存碎片化。
编码优化
针对性能要求较高的场景使用ziplist,建议长度不要超过1000,每个元素大小控制在512字节以内。
当集合只包含整数且长度不超过set-max-intset-entries配置时使用intset编码。
对于大量小对象的存储场景,非常适合使用ziplist编码的hash类型控制键的规模来降低内存。
三、参考资料
设置Redis最大占用内存
Redis的内存优化
Redis禁用命令、危险命令及规避方法
Redis debugging guide
Playing with ptrace, Part I
神器strace, ltrace
How to disable Redis RDB?
Redis研究(十九)—命令属性
Virtual memory settings in Linux - The Problem with Overcommit
What is the logic behind killing processes during an Out of Memory situation?
How to reproduce a condition which invokes the OOM-Killer ?

<think>首先,用户的问题是关于如何退出Redis哨兵模式中的倾斜模式(Tilt mode)。根据引用[4],有提到redis哨兵频繁提示tilt mode exited进入倾斜模式,并提供了几个链接。 我需要回顾系统级指令: - 所有行内数学表达式必须使用$...$格式,但这个问题似乎不涉及数学表达式,所以可能不需要。 - 独立公式必须使用$$...$$格式,但同样,不涉及。 - LaTeX语法正确:确保任何数学表达正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 参考站内引用:用户提供了引用[1]到[4],我需要基于这些来回答。 用户的问题:"请问如何退出Redis哨兵模式中的倾斜模式" 从引用[4]中: - 它提到redis哨兵频繁提示tilt mode exited进入倾斜模式。 - 提供了几个链接:GitHub issue, 51CTO文章, StackOverflow, coder.work文章。 这些引用是关于问题的描述,但没有直接给出解决方案。用户要求退出倾斜模式,所以我需要基于这些信息提供步骤。 倾斜模式(Tilt mode)是Redis哨兵中的一个状态,当系统检测到可能的问题(如时间不一致或性能问题)时,它会进入这个模式以保护系统。在倾斜模式下,哨兵不会执行故障转移操作。 如何退出倾斜模式: 1. **理解倾斜模式的原因**:倾斜模式通常由系统时间变化、性能问题或配置问题触发。引用[4]的链接可能提供更多细节。 2. **检查日志**:查看哨兵日志以确定进入倾斜模式的原因。日志中会显示"tilt mode entered"和"tilt mode exited"。 3. **解决根本问题**: - 确保系统时间同步(使用NTP服务)。 - 检查系统负载和性能问题。 - 验证哨兵配置。 4. **等待自动退出**:倾斜模式通常是临时的。哨兵在进入倾斜模式后一段时间(默认30秒)会自动退出,如果问题解决。 5. **手动干预**:如果问题持续,可能需要重启哨兵或调整配置。 根据引用[4]的链接: - GitHub issue #10547 可能讨论相关问题。 - 51CTO文章可能提供解决方案。 - StackOverflow链接提到当RAID检查运行时进入倾斜模式,表明时间不一致或系统中断可能触发。 我需要综合这些提供步骤。 回答结构: 1. **解释倾斜模式**:简要说明什么是倾斜模式。 2. **原因分析**:列出常见原因。 3. **退出步骤**:提供如何退出倾斜模式的步骤。 4. **预防措施**:如何避免再次进入倾斜模式。 5. **生成相关问题**:在末尾添加相关问题。 引用标识:在回答中,当引用特定部分时添加[^数字],但用户提供的引用是站内的,所以我应该基于这些引用。 用户提供的引用: - [^1]: 关于主从模式和哨兵的基本介绍。 - [^2]: 详细哨兵模式,包括选举和故障转移。 - [^3]: 哨兵+主从的问题,如内存限制。 - [^4]: 关于倾斜模式的问题。 对于这个问题,引用[^4]最相关。 回答大纲: 1. 介绍倾斜模式:倾斜模式是Redis哨兵的一种保护机制,当检测到潜在问题时(如时间不一致),它会暂停某些操作。 2. 退出方法: - 自动退出:哨兵在进入倾斜模式后,如果问题解决,会在一段时间后自动退出。 - 手动步骤:检查系统时间、负载;重启哨兵;调整配置。 3. 详细步骤: - 检查哨兵日志确认原因。 - 同步系统时间(使用NTP)。 - 确保系统性能稳定。 - 如果必要,重启哨兵进程。 4. 预防:配置NTP,监控系统性能。 生成相关问题: 1. 如何配置Redis哨兵以避免进入倾斜模式? 2. Redis哨兵倾斜模式对系统有什么影响? 3. 如何监控Redis哨兵的状态? 确保回答真实可靠:基于Redis官方文档和常见实践。</think>### 如何退出Redis哨兵模式中的倾斜模式(Tilt Mode) Redis哨兵模式中的倾斜模式(Tilt Mode)是一种保护机制,当哨兵检测到系统时间不一致、性能问题(如高负载)或意外中断时,会自动进入该状态。在倾斜模式下,哨兵会暂停故障转移操作,以防止误判导致的数据不一致问题[^4]。退出倾斜模式需要解决根本原因,以下是清晰的步骤指南: #### 1. **理解倾斜模式的原因** - 倾斜模式通常由以下情况触发: - **系统时间不同步**:服务器时钟漂移或未使用NTP(Network Time Protocol)同步。 - **性能问题**:CPU、内存或I/O负载过高,导致哨兵心跳检测超时。 - **外部干扰**:如RAID检查、硬件故障或网络抖动[^4]。 - 哨兵默认在进入倾斜模式后30秒自动尝试退出(如果问题解决),但问题持续时需手动干预。 #### 2. **检查哨兵日志以确认原因** - 查看哨兵日志文件(默认路径:`/var/log/redis/sentinel.log`),搜索关键词如 `tilt mode entered` 或 `tilt mode exited`。 - 示例日志分析: - 如果日志显示 `+tilt #tilt mode entered`,表示进入倾斜模式。 - 如果显示 `-tilt #tilt mode exited`,表示已自动退出。 - 常见错误信息:如 `clock jumped`(时间跳跃)或 `timeout`(超时)可帮助定位问题[^4]。 #### 3. **退出倾斜模式的步骤** - **自动退出(推荐等待)**: - 如果问题短暂(如网络抖动),哨兵通常在30-60秒内自动退出倾斜模式。无需操作,但需监控日志确认状态变化。 - **手动退出(当问题持续时)**: 1. **同步系统时间**: - 安装并配置NTP服务,确保所有Redis节点时间一致。 - 命令示例: ```bash sudo apt install ntp # Ubuntu/Debian sudo systemctl restart ntp ntpq -p # 检查时间同步状态 ``` 2. **优化系统性能**: - 检查CPU、内存和磁盘使用率(使用 `top` 或 `htop`)。 - 降低负载:如减少Redis实例数量、优化查询或升级硬件。 - 确保哨兵配置中的 `down-after-milliseconds` 参数合理(默认5000毫秒),避免因短暂延迟触发倾斜模式[^2]。 3. **重启哨兵服务**: - 如果以上步骤无效,重启哨兵进程以重置状态: ```bash sudo systemctl restart redis-sentinel # 或使用 sentinel 服务名 ``` - 重启后检查日志确认是否退出倾斜模式。 4. **调整哨兵配置**: - 在哨兵配置文件(如 `sentinel.conf`)中,增加 `tilt-timeout` 参数(单位毫秒),延长自动退出等待时间(默认30000毫秒): ``` sentinel tilt-timeout 60000 # 设置为60秒 ``` - 重启哨兵使配置生效。 #### 4. **预防倾斜模式的措施** - **强制时间同步**:部署NTP服务并设置定期同步(如每天一次)。 - **监控与告警**:使用工具如Prometheus或Redis自带的 `INFO` 命令监控哨兵状态,设置告警规则。 - **优化环境**:避免在高峰时段运行维护任务(如RAID检查),确保网络稳定。 - **定期维护**:更新Redis到最新版本(修复已知bug),并审查哨兵日志。 如果问题持续,请参考Redis官方文档或社区资源(如提供的GitHub issue #10547[^4])进行深入排查。倾斜模式是保护机制,正确处理可确保哨兵的高可用性[^1][^2]。 ### 相关问题 1. 如何配置Redis哨兵以避免频繁进入倾斜模式? 2. Redis哨兵倾斜模式对故障转移有什么影响? 3. 如何监控Redis哨兵的状态和性能指标? [^1]: 在主从模式中,一旦主节点挂了,那么就只剩下从节点了;虽然能够提供读操作,但是不能写入数据,从节点不能自动的升级为主节点,不能替原来主节点对应的角色;通过人工的方式太不靠谱了(人不能一天24个小时盯着机器看),所有此时Redis提供了“哨兵”机制就是为了解决这一问题,让程序保存“高可用”状态~ [^2]: 哨兵探测主节点是否异常是用的心跳机制,就是每隔一段时间,向主节点发送ping进而保持连接。 [^3]: 假设我们在一台主从机器上配置了200G内存,但是业务需求是需要500G的时候,主从结构+哨兵可以实现高可用故障切换+冗余备份,但是并不能解决数据容量的问题。 [^4]: redis哨兵频繁提示tilt mode exited进入倾斜模式。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值