redis RDB快照失败导致redis命令执行错误

概述

  • 问题
  • 解决

问题

环境:window10 内存16G 4核
场景:使用redis存储一些高并发读写的数据,并发测试的时候偶发RDB快照失败,导致redis命令无法执行。

客户端报错:

MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.

根据该报错我们去找redis server的日志详细了解关于这个RDB error(当时我的redis是装在自己电脑上的,默认情况下redis log文件在redis安装文件的根级目录下,和redis-server.exe一个目录,redis-server.log)

=== REDIS BUG REPORT START: Cut & paste starting from here ===
Redis version: 5.0.9
[16668] 16 Oct 20:52:03.200 # --- EXCEPTION_ACCESS_VIOLATION
[16668] 16 Oct 20:52:03.201 # --- STACK TRACE
redis-server.exe!StackTraceInfo(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:153)(0x14018CBB0, 0x0014FF60, 0x1400DD020, 0x0014DF00)
redis-server.exe!UnhandledExceptiontHandler(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x0014DF00, 0x1400DD001, 0x00000000, 0x7FCD35004F57)
KERNELBASE.dll!UnhandledExceptionFilter(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x00000000, 0x7FF996AC43B8, 0x00000000, 0x0014FEF0)
ntdll.dll!memset(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x00000000, 0x00000000, 0x0014E4C8, 0x0014E550)
ntdll.dll!_C_specific_handler(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x00000000, 0x0014E4B0, 0x0014EB70, 0x0014EB70)
ntdll.dll!_chkstk(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x00000001, 0x7FF996980000, 0x00000000, 0x7FF996AEE9E4)
ntdll.dll!RtlRaiseException(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x00000000, 0x00000000, 0x0001D389, 0x00000000)
ntdll.dll!KiUserExceptionDispatcher(D:\dev\GitHub\redis\src\Win32_Interop\Win32_StackTrace.cpp:186)(0x7FCD29C28850, 0x41D7E265DC800000, 0x00148563, 0x0001D36E)
redis-server.exe!rdbSaveObject(D:\dev\GitHub\redis\src\rdb.c:869)(0x00000001, 0x140048105, 0x00000009, 0x0014F1F0)
redis-server.exe!rdbSaveKeyValuePair(D:\dev\GitHub\redis\src\rdb.c:1072)(0x0014F1F0, 0x00000000, 0x06C00000, 0x00000009)
redis-server.exe!rdbSaveRio(D:\dev\GitHub\redis\src\rdb.c:1216)(0x018BDDC0, 0x00DC0000, 0x00000000, 0x0000411C)
redis-server.exe!rdbSave(D:\dev\GitHub\redis\src\rdb.c:1318)(0x02098A08, 0x00DC0000, 0x00DC0000, 0x0000009D)
redis-server.exe!QForkChildInit(D:\dev\GitHub\redis\src\Win32_Interop\Win32_QFork.cpp:297)(0x00000210, 0x00000000, 0x00000210, 0x0045F4D0)
redis-server.exe!main(D:\dev\GitHub\redis\src\Win32_Interop\Win32_QFork.cpp:1136)(0x00000000, 0x00000000, 0x004450D0, 0x00000000)
redis-server.exe!__scrt_common_main_seh(d:\agent_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)(0x00000000, 0x00000000, 0x00000000, 0x00000000)
KERNEL32.DLL!BaseThreadInitThunk(d:\agent_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)(0x00000000, 0x00000000, 0x00000000, 0x00000000)
ntdll.dll!RtlUserThreadStart(d:\agent_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)(0x00000000, 0x00000000, 0x00000000, 0x00000000)
ntdll.dll!RtlUserThreadStart(d:\agent_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)(0x00000000, 0x00000000, 0x00000000, 0x00000000)

解决

通过日志我们可以知道这是因为RDB快照失败导致的命令无法执行,在redis中我们可以设置忽略这个错误,即快照失败依然可以进行执行命令。

redis配置项中关于这个的配置项名称为stop-writes-on-bgsave-error,默认值为yes,我们需要改为no。
可以直接在client上执行命令:

config set stop-writes-on-bgsave-error no

这个修改是一次性的,只会修改redis当前运行的内存中的配置项的值,如果需要永久修改我们需要在redis配置文件redis.conf中修改stop-writes-on-bgsave-error的值。

解决RDB快照失败:

原因

一:快照文件当前登录用户无写权限
二:磁盘空间不足
三:因为bgsave需要fork一个子进程,如果内存不足以fork子进程的话也会报错

根据以上三个原因的解决方案有:

一:设置快照文件的写权限
二:清理磁盘空间
三:清理内存或者设置系统参数允许放行fork子进程当内存不足的时候,在linux内核中的vm.overcommit_memory参数(window暂时不知道怎么改)

如果 vm.overcommit_memory = 1,直接放行
vm.overcommit_memory = 0:则比较 此次请求分配的虚拟内存大小和系统当前空闲的物理内存加上swap,决定是否放行。
vm.overcommit_memory = 2:则会比较 进程所有已分配的虚拟内存加上此次请求分配的虚拟内存和系统当前的空闲物理内存加上swap,决定是否放行。

posted @ 2020-10-22 22:57  無花無酒鋤作田  阅读(3491)  评论(0编辑  收藏  举报