MISCONF Redis配置为保存RDB快照

Sal*_*ali 316 redis

在写入Redis(SET foo bar)期间,我收到以下错误:

MISCONF Redis配置为保存RDB快照,但目前无法在磁盘上保留.可以修改可能修改数据集的命令.请检查Redis日志以获取有关错误的详细信息.

基本上我明白问题是redis无法在磁盘上保存数据,但不知道如何摆脱这个问题.

此外,下面的问题有同样的问题,它很久以前就被抛弃,没有答案,很可能没有尝试解决问题.

小智 277

您可以停止尝试保存快照:

config set stop-writes-on-bgsave-error no
Run Code Online (Sandbox Code Playgroud)

这是一个快速的解决方法,但是如果你关心你正在使用它的数据,你应该检查以确定为什么bgsave首先失败.

  • 这是一个快速的解决方法,但你应该检查以确保为什么bgsave首先失败 (17认同)
  • 如果您主要使用redis进行缓存和会话,那么这是必须的. (7认同)
  • 这不危险吗?例如,NodeBB使用Redis作为数据存储。 (3认同)
  • 每当我重新启动服务器时,我都会再次遇到相同的问题。然后,我必须再次设置它。我如何使其永久化? (3认同)
  • IMO绝对不是解决方案。您只是告诉 Redis 不要记录这些错误。但错误仍然存​​在... (3认同)
  • @LoveToCode config set stop-writes-on-bgsave-error yes (2认同)
  • @ZiaQamar - 您需要保存配置文件中的更改才能持久 (2认同)
  • 具有讽刺意味的是,针对有关持久更改的错误的建议解决方案是配置更改,但未保存在磁盘上。每个人都认为他们永远不会重新启动服务器吗?每个人都拥有如此美好的记忆,以至于他们总是记得重新启动时所做的每一个配置更改吗? (2认同)

Ero*_*lin 246

重启你的 redis 服务器。

  • MACOS(BREW) :brew services restart redis
  • Linux: sudo service redis restart /sudo systemctl restart redis
  • Windows: Windows + R-> Type services.mscEnter-> Search forRedis然后点击restart

我个人在使用 Brew ( brew upgrade)升级 redis 后遇到了这个问题。重新启动笔记本电脑后,它立即工作。

  • 经典的“您是否尝试过将其关闭并再次打开”答案有帮助 (21认同)
  • 伙计,这太明显了)谢谢 (8认同)
  • 这真是太神奇了!就我而言,我经常对软件包进行brew升级,并且“brew服务重新启动redis”就是票证。干杯。 (4认同)
  • 它也对我有用,我在通过brew“brew升级”升级redis时遇到了同样的问题。就我而言,我升级了brew包来解决这个问题:/sf/ask/3768022401/错误运行/54873233#comment117630628_54873233 (3认同)

Axe*_*nto 162

如果您遇到错误并且某些重要数据无法在正在运行的redis实例上丢弃(rdb文件或其目录的权限问题不正确或磁盘空间不足),您始终可以将rdb文件重定向到其他位置.

使用redis-cli,您可以这样做:

CONFIG SET dir /tmp/some/directory/other/than/var
CONFIG SET dbfilename temp.rdb
Run Code Online (Sandbox Code Playgroud)

在此之后,您可能希望执行BGSAVE命令以确保将数据写入rdb文件.确保当你执行INFO,bgsave_in_progress已经是0(无论操作成功或有遇到错误).之后,您现在可以开始在rdb安全的地方备份生成的文件.

  • rdb_bgsave_in_progress:持久性下的0 (5认同)
  • 对于那些在Windows上不幸的人,我现在,以及谁正在使用MSOpenTech版本,你必须设置以下样式的目录路径:`dir C:/ Temp /`.做一个bgsave来验证它的工作原理.. (5认同)
  • `BGSAVE` 不会立即告诉您它是失败还是成功。您必须先重复执行“INFO persistence”,然后等待“rdb_bgsave_in_progress”变为“0”。之后,检查rdb_last_bgsave_status是否为ok。 (3认同)
  • 127.0.0.1:6379> CONFIG SET dir /root/tool (错误) ERR 更改目录:权限被拒绝 (2认同)

Chr*_*ris 56

由于内存不足,在bgsave过程中可能会出现错误.试试这个(来自redis背景保存常见问题)

echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
Run Code Online (Sandbox Code Playgroud)

  • LInk:http://redis.io/topics/faq搜索:"*即使我有大量的空闲RAM,背景保存也会因Linux下的fork()错误而失败!*" (5认同)

Tou*_*aza 50

就我而言,这只是我需要允许 Redis 接受传入请求的权限。

所以我通过 Homebrew 重新启动了 Redis 服务brew services stop redis,并brew services start redis在本地运行 Redis 服务器redis-server。命令提示符要求我允许传入的请求,它开始工作。

  • 谢谢。我在 Mac 上通过自制软件更新后发生了这种情况。 (4认同)

Bhi*_*ndi 34

发生此错误是因为BGSAVE失败.在BGSAVE期间,Redis分叉子进程将数据保存在磁盘上.虽然BGSAVE失败的确切原因可以从日志中检查(通常在/var/log/redis/redis-server.loglinux机器上),但很多时候BGAVE失败,因为fork无法分配内存.很多时候,由于操作系统的优化冲突,fork无法分配内存(尽管机器有足够的RAM可用).

Redis FAQ中可以读到:

Redis后台保存模式依赖于现代操作系统中fork的copy-on-write语义:Redis forks(创建子进程),它是父进程的精确副本.子进程将数据库转储到磁盘上,最后退出.理论上,孩子应该使用尽可能多的内存作为副本,但实际上由于大多数现代操作系统实现的写时复制语义,父和子进程将共享公共内存页.只有在子页面或父级页面中发生更改时,页面才会重复.由于理论上所有页面都可能在子进程保存时发生变化,因此Linux无法预先知道子进程将占用多少内存,因此如果将overcommit_memory设置设置为零,则fork将失败,除非有尽可能多的可用RAM需要真正复制所有父内存页面,结果是如果你有一个3 GB的Redis数据集和2 GB的可用内存,它将失败.

将overcommit_memory设置为1表示Linux放松并以更乐观的分配方式执行fork,这确实是你想要的Redis.

Redis不需要像操作系统认为写入磁盘那样多的内存,因此可能会先发生故障.

要解决此问题,您可以:

修改/etc/sysctl.conf并添加:

vm.overcommit_memory=1
Run Code Online (Sandbox Code Playgroud)

然后使用以下命令重启sysctl:

在FreeBSD上:

sudo /etc/rc.d/sysctl reload
Run Code Online (Sandbox Code Playgroud)

在Linux上:

sudo sysctl -p /etc/sysctl.conf
Run Code Online (Sandbox Code Playgroud)


smi*_*e89 23

如果您正在使用Linux机器,还要重新检查数据库的文件和文件夹权限.

db及其路径可以通过以下方式获得:

redis-cli:

配置GET目录

CONFIG GET dbfilename

并在命令行中ls -l.目录的权限应为755,文件的权限应为644.此外,通常redis-server作为用户执行redis,因此redis通过执行也可以为用户提供文件夹的所有权sudo chown -R redis:redis /path/to/rdb/folder.这里的答案已经详细说明了这一点.


Sal*_*ali 20

谢谢大家检查问题,显然错误发生在bgsave.

对我来说,输入config set stop-writes-on-bgsave-error noshell并重新启动Redis解决了这个问题.

  • 这并没有"解决问题",它只是忽略了它. (71认同)
  • IMO绝对不是解决方案。您只是告诉 Redis 不要记录这些错误。但错误仍然存​​在... (2认同)

Fus*_*ush 18

如果您运行的是 MacOS 并且最近升级到 Catalina,则可能需要brew services restart redis按照本期中的建议运行。


Gov*_*Rai 15

在Redis具有写入权限的目录中启动Redis Server

上面的答案肯定会解决你的问题,但这是实际发生的事情:

存储rdb.dump文件的默认位置是./(表示当前目录).您可以在redis.conf文件中验证这一点.因此,启动redis服务器的dump.rdb目录是创建和更新文件的位置.

您似乎已经开始在redis服务器上运行redis服务器,其中redis没有正确的权限来创建该dump.rdb文件.

更糟糕的是,redis也可能不允许您关闭服务器,直到它能够创建rdb文件以确保正确保存数据.

要解决此问题,您必须使用redis-cli并更新dir密钥并进入活动的redis客户端环境,并将其值设置为项目文件夹或非root用户有权保存的任何文件夹.然后运行BGSAVE以调用dump.rdb文件的创建.

CONFIG SET dir "/hardcoded/path/to/your/project/folder"
BGSAVE
Run Code Online (Sandbox Code Playgroud)

(现在,如果您需要将dump.rdb文件保存在启动服务器的目录中,那么您将需要更改目录的权限,以便redis可以写入该目录.您可以搜索stackoverflow以了解如何执行此操作).

您现在应该可以关闭redis服务器了.请注意,我们对路径进行了硬编码.硬编码很少是一种很好的做法,我强烈建议从项目目录启动redis服务器并更改dir key back to./`.

CONFIG SET dir "./"
BGSAVE
Run Code Online (Sandbox Code Playgroud)

这样,当你需要redis用于另一个项目时,转储文件将在你当前项目的目录中创建,而不是在硬编码路径的项目目录中.


Bin*_* Ho 10

在线redis.conf~235我们尝试像这样更改配置

- stop-writes-on-bgsave-error yes
+ stop-writes-on-bgsave-error no
Run Code Online (Sandbox Code Playgroud)

  • 注意:在 macOS 上,此文件位于 /usr/local/etc/redis.conf,您需要运行此命令来重新启动 redis:brew services restart redis (7认同)

小智 9

曾遇到此错误,并且能够从日志中找出该错误是由于磁盘空间不足所致。在我的情况下,不再需要插入的所有数据。所以我试着去冲洗。由于redis-rdb-bgsave进程正在运行,因此也不允许刷新数据。我按照以下步骤操作,可以继续。

  1. 登录到Redis客户端
  2. 执行配置设置bgsave-stops-writes-on错误
  3. 执行FLUSHALL(不需要存储数据)
  4. 执行配置设置bgsave-stops-writes-on-bgsave-error是

完成上述步骤后,进程redis-rdb-bgsave不再运行。


bha*_*man 8

我遇到了类似的问题,这背后的主要原因是 redis 消耗的内存(RAM)。我的 EC2 机器有 8GB RAM(可用 7.4 左右)

当我的程序运行时,RAM 使用量上升到 7.2 GB,在 RAM 中几乎没有~100MB,这通常会触发 MISCONF Redis error ...

您可以使用该htop命令确定 RAM 消耗。运行 htop 命令后查找Mem属性。如果它显示高消耗(例如在我的情况下是 7.2GB/7.4GB),最好升级具有更大内存的实例。在这种情况下,使用config set stop-writes-on-bgsave-error no将对服务器造成灾难,并可能导致服务器上运行的其他服务(如果有)中断。因此,最好避免使用 config 命令并升级您的 Redis MACHINE

仅供参考:您可能需要安装htop才能完成这项工作:sudo apt-get install htop

对此的另一种解决方案可能是在您的系统上运行其他一些 RAM 繁重的服务,检查您的服务器/机器/实例上运行的其他服务,并在不需要时停止它。要检查机器上运行的所有服务,请使用service --status-all

对于直接粘贴 config 命令的人的建议,请重新搜索一下,至少在使用此类命令之前警告用户。正如@Rodrigo 在他的评论中提到的那样:“忽略错误看起来并不酷。”

- -更新 - -

您还可以配置maxmemorymaxmemory-policy定义达到特定内存限制时 Redis 的行为。例如,如果我想保持6GB的内存限制,并从DB中删除最近最少使用的键,以确保redis mem使用量不超过6GB,那么我们可以设置这两个参数(在redis.conf或CONFIG SET中)命令):

maxmemory 6gb
maxmemory-policy allkeys-lru
Run Code Online (Sandbox Code Playgroud)

您可以为这两个参数设置许多其他值,您可以从这里阅读:https : //redis.io/topics/lru-cache


mir*_*phd 6

如今,向客户端提供此错误消息的 Redis 写访问问题重新出现在官方redisdocker 容器中。

官方redis镜像中的Redis尝试将 .rdb 文件写入到容器/data文件夹中,这是相当不幸的,因为它是一个根拥有的文件夹,而且它也是一个非持久位置(如果您的容器/pod,写入那里的数据将消失)崩溃)。

因此,在闲置一小时后,如果您redis以非 root 用户身份运行容器(例如,docker run -u 1007而不是 default docker run -u 0),您将在服务器日志中收到非常详细的错误消息(请参阅参考资料docker logs redis):

1:M 29 Jun 2019 21:11:22.014 * 1 changes in 3600 seconds. Saving...
1:M 29 Jun 2019 21:11:22.015 * Background saving started by pid 499
499:C 29 Jun 2019 21:11:22.015 # Failed opening the RDB file dump.rdb (in server root dir /data) for saving: Permission denied
1:M 29 Jun 2019 21:11:22.115 # Background saving error
Run Code Online (Sandbox Code Playgroud)

所以你需要做的是将容器的/data文件夹映射到外部位置(非root用户,这里:1007,具有写访问权限,例如/tmp在主机上),例如:

docker run --rm -d --name redis -p 6379:6379 -u 1007 -v /tmp:/data redis
Run Code Online (Sandbox Code Playgroud)

因此,这是官方 docker 映像(应该写入/tmpnot /data)的错误配置产生了这个“定时炸弹”,您很可能只会在生产中遇到……在某个特别安静的假期周末过夜:/

  • 只是想在这里添加一条评论,因为这最终帮助解决了我在 Docker 中使用 redis 时遇到的问题。我们的 UAT 和 Dev Docker 服务器是 Windows。Windows Defender 会将 RDB 文件识别为潜在病毒。因此,挂载 /data 目录将暂时解决父问题;直到 Windows Defender 隔离该文件,从而导致另一个文件。请确保在 Windows Defender 中将装载的数据目录添加为例外,以解决此问题。 (2认同)
  • 提醒我:Windows Defender 警报不一定是误报 - 即使在没有 root 且所有功能均已删除的情况下运行时,加密挖矿程序也可以感染官方 Redis 映像 - 将其端口暴露到网络就足够了 (2认同)
  • 是的,有效负载可能无法在 Windows 上执行,除非完全用 Lua 编写,从而像 Redis 本身一样跨平台…… eval 命令是魔鬼的发明,无论使用哪种语言 (2认同)
  • 这是一次启发性的经历;非常感谢。显然,我们的 UAT/DEV 组合文件暴露了 Docker 网络之外的端口。我不知道这是怎么可能的,但这些实例确实正在接收管理命令。正在推出加密货币矿工。我已经禁用了这些端口,关闭了本地 RDB 挂载,并重新设置了 Windows Defender 异常(不过,这与挂载关闭无关)。我需要调查这些命令是如何通过我们的防火墙的,但我正在密切监视 (2认同)

小智 6

为了我

config set stop-writes-on-bgsave-error no
Run Code Online (Sandbox Code Playgroud)

然后我重新加载我的 mac,它可以工作


小智 6

$ redis-cli

config set stop-writes-on-bgsave-error 没有

根据 Redis 文档,仅当您没有启用 RDB 快照或者您不关心快照中的数据持久性时才建议这样做。

“默认情况下,如果启用了 RDB 快照(至少一个保存点)并且最新的后台保存失败,Redis 将停止接受写入。这将使用户意识到(以一种艰难的方式)数据没有正确地保存在磁盘上,否则,强烈的文本机会是没有人会注意到并且会发生一些灾难。”

你应该做的是:

redis-cli

127.0.0.1:6379> CONFIG SET dir /data/tmp OK 127.0.0.1:6379> CONFIG SET dbfilename temp.rdb OK 127.0.0.1:6379> BGSAVE 后台保存开始127.0.0.1/tmptmp9>请确定/6379有足够的磁盘空间。


小智 6

是的,发生这种情况是因为当前用户没有修改“dump.rdb”的权限。

因此,您也可以向旧文件授予权限(更改其所有权),而不是创建新的 RDB 文件。

在 redis-cli 中输入:

config get dir

你会得到“/usr/local/var/db/redis”(这是redis写入数据的位置)

使用终端转到此位置

cd 
cd /usr/local/var/db
Run Code Online (Sandbox Code Playgroud)

输入此命令(使用我们的用户名):

sudo chown -R [username] db
Run Code Online (Sandbox Code Playgroud)

这将更改为所有者。

这对我有用。


Rya*_*lly 5

FWIW,我遇到了这个问题,解决方案是简单地向框中添加一个交换文件。我使用了这种方法:https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04

  • @DarthSpeedious 在 Redis 日志中,您会看到“*无法分配内存*”错误。有关如何查看日志文件的信息,请参阅此处:http://stackoverflow.com/questions/16337107/how-to-access-redis-log-file (2认同)

小智 5

一个更永久的修复可能是在/etc/redis/redis.conf周围查看200-250行有rdb功能的设置,这些设置在2.x天内不再是redis的一部分.

特别是

dir ./
Run Code Online (Sandbox Code Playgroud)

可以改为

dir /home/someuser/redislogfiledirectory
Run Code Online (Sandbox Code Playgroud)

或者您可以注释掉所有保存行,而不用担心持久性.(参见/etc/redis/redis.conf中的评论)

另外,别忘了

service redis-server stop
service redis-server start
Run Code Online (Sandbox Code Playgroud)


car*_*ing 5

所有这些答案都不能解释为什么rdb保存失败的原因。


作为我的案例,我检查了redis日志并发现:

14975:M 18 Jun 13:23:07.354#通过信号9终止后台保存

在终端中运行以下命令:

sudo egrep -i -r 'killed process' /var/log/
Run Code Online (Sandbox Code Playgroud)

它显示:

/var/log/kern.log.1:Jun 18 13:23:07 10-10-88-16内核:[28152358.208108]杀死了进程28416(redis-server)total-vm:7660204kB,anon-rss:2285492kB,文件-rss:0kB

这就对了!此过程(redis save rdb)被OOM杀手杀死

指:

https://github.com/antirez/redis/issues/1886

查找哪个进程被Linux OOM杀手杀死了


小智 5

我知道这个线程有点旧,但是当我早些时候收到此错误时,这对我有用,因为我知道我远未接近内存限制 - 这两个答案都在上面找到。

希望这可以帮助将来需要的人。

  1. 检查了 dir 文件夹上的 CHMOD...发现符号表示法不同。CHMOD dir 文件夹到 755
  2. dbfilename 权限良好,无需更改
  3. 重新启动redis服务器
  4. (本来应该先这样做的,但是啊好吧)参考了redis-server.log,发现错误是访问被拒绝的结果。

再次不确定 DIR 文件夹的权限是如何更改的,但我假设 CHMOD 回到 755 并重新启动 redis-server 就可以解决这个问题,因为之后我能够 ping redis 服务器。

另请注意,redis 确实拥有 dbfilename 和 DIR 文件夹的所有权。