MISCONF Redis 配置为保存 RDB 快照

Posted

技术标签:

【中文标题】MISCONF Redis 配置为保存 RDB 快照【英文标题】:MISCONF Redis is configured to save RDB snapshots 【发布时间】:2013-11-04 01:16:49 【问题描述】:

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

,但当前 无法在磁盘上持久化。可能修改数据集的命令是 禁用。有关错误的详细信息,请查看 Redis 日志。

基本上我知道问题是redis无法将数据保存在磁盘上,但不知道如何解决这个问题。

the following question 也有同样的问题,很久以前就放弃了,没有答案,很可能没有尝试解决问题。

【问题讨论】:

您能否解决此问题。如果是,请您协助完成这些步骤。因为我猜将 rdb 文件放在其他地方不会解决它。我想我在这里遗漏了一些东西 这个错误是因为在redis没有权限的目录下启动redis服务器。我建议在解决问题后恢复为默认设置:请参阅 answer 了解有关此问题的修复。 除了 Govind Rai 的回答:***.com/a/47880440/5649620 @GovindRai 我已经通过将组和所有者更改为 redis 来授予 redis 权限,但没有帮助! 作为第一次快速检查,请确保磁盘上有剩余空间 【参考方案1】:

使用redis-cli,您可以阻止它尝试保存快照:

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

这是一个快速的解决方法,但如果您关心使用它的数据,您应该首先检查以确定 bgsave 失败的原因。

【讨论】:

这是一个快速的解决方法,但您应该首先检查以确定 bgsave 失败的原因 如果你主要用redis做缓存和会话,这个是必须的。 这不危险吗?例如,NodeBB 使用 Redis 作为数据存储。 @LoveToCode 配置设置 stop-writes-on-bgsave-error 是 每当我重新启动服务器时,我都会再次遇到同样的问题。然后我必须重新设置它。我怎样才能让它永久化?【参考方案2】:

重启你的 redis 服务器。

ma​​cOS (brew)brew services restart redis. Linux: sudo service redis restart / sudo systemctl restart redis Windows: Windows + R -> 输入services.msc回车 -> 搜索Redis 然后点击在restart

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

【讨论】:

如果有人在读这篇文章,我也遇到了 Homebrew 的问题,但与升级无关:我只需要使用 sudo:brew services stop redis; sudo brew services start redis 启动服务。 伙计,这太明显了)谢谢 经典的“您是否尝试过将其关闭然后重新打开”的答案有帮助 在我的情况下(macOS),它有效!我认为是 Big Sur 更新导致的,因此某些 brew 系统需要更新一次 我尝试brew uninstall redisbrew install redis 重新安装,但没有成功,但成功了!【参考方案3】:

如果遇到错误,在运行的redis实例上某些重要数据无法丢弃(rdb文件或其目录权限错误,或者磁盘空间不足),可以随时重定向@ 987654322@ 文件写入其他地方。

使用redis-cli,您可以执行以下操作:

CONFIG SET dir /tmp/some/directory/other/than/var
CONFIG SET dbfilename temp.rdb

之后,您可能需要执行BGSAVE 命令以确保将数据写入rdb 文件。确保当你执行INFO persistence时,bgsave_in_progress已经是0并且rdb_last_bgsave_statusok。之后,您现在可以开始将生成的rdb 文件备份到安全的地方。

【讨论】:

rdb_bgsave_in_progress:0 在 Persistence 下 由于某种原因,当我尝试任何配置集命令时,它就像永远加载一样。 对于那些在 Windows 上的不幸的人,我现在和哇正在使用 MSOpenTech 版本,您必须按照以下样式设置目录路径:dir C:/Temp/。执行 bgsave 以验证它是否有效.. 127.0.0.1:6379> CONFIG SET dir /root/tool (error) ERR 更改目录:权限被拒绝 BGSAVE 不会立即告诉您它是失败还是成功。你必须先重复INFO persistence,然后等到rdb_bgsave_in_progress变成0。之后,检查rdb_last_bgsave_status是否为ok【参考方案4】:

由于内存不足,在 bgsave 过程中可能会出现错误。试试这个(来自redis后台保存FAQ)

echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1

【讨论】:

LInk: redis.io/topics/faq 搜索此内容:“即使我有很多可用 RAM,在 Linux 下后台保存也会失败并出现 fork() 错误!【参考方案5】:

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

可以从Redis FAQ阅读:

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

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

Redis 不需要操作系统认为它写入磁盘所需的那么多内存,因此可能会先发制人地使 fork 失败。

要解决这个问题,您可以:

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

vm.overcommit_memory=1

然后重启 sysctl:

在 FreeBSD 上:

sudo /etc/rc.d/sysctl reload

在 Linux 上:

sudo sysctl -p /etc/sysctl.conf

【讨论】:

systemctl status redis 的输出显示有一条警告建议完全更改 overcommit_memory=0 设置。改变这确实解决了我的问题。 这正确解决了问题,应该是公认的答案 所以 tldr 在默认设置下是这样的 @DanHastings - 是的。并且将 overcommit_memory 设置为 1 可以放宽这个要求。 @Bhindi:非常感谢 - 这对我来说非常有用!!!!一个快速的问题是这是否会影响任何其他与 sidekiq 相关的流程或任何重要的事情?【参考方案6】:

如果您在 linux 机器上工作,还要重新检查数据库的文件和文件夹权限。

可以通过以下方式获得数据库及其路径:

redis-cli:

配置获取目录

配置获取数据库文件名

在命令行中ls -l。目录的权限应该是755,文件的权限应该是644。此外,通常 redis-server 以用户 redis 的身份执行,因此通过执行 sudo chown -R redis:redis /path/to/rdb/folder 来授予用户 redis 文件夹的所有权也很好。这已在答案here中详细说明。

【讨论】:

他们应该是什么权限?【参考方案7】:

感谢大家排查问题,显然错误是在bgsave期间产生的。

对我来说,在 shell 中输入 config set stop-writes-on-bgsave-error no 并重新启动 Redis 即可解决问题。

【讨论】:

这并没有“解决问题”,只是忽略了它。 在 Services.msc 中重新启动 RedisServer 对我有用。 每当我重新启动服务器时,我都会再次遇到同样的问题。然后我必须重新设置它。我怎样才能让它永久化? @ZiaQamar,你可以在redis.conf中永久设置属性,很可能在/etc/redis/redis.conf,设置“stop-writes-on-bgsave-error no” IMO 绝对不是解决方案。您只是告诉 Redis 不要记录这些错误。但是错误仍然存​​在...【参考方案8】:

如果您正在运行 MacOS 并且最近升级到 Catalina,您可能需要按照 this issue 中的建议运行 brew services restart redis

【讨论】:

【参考方案9】:

在Redis有写权限的目录下启动Redis Server

上面的答案肯定会解决你的问题,但实际情况如下:

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

您似乎已经开始在 redis 没有正确权限创建 dump.rdb 文件的目录中运行 redis 服务器。

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

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

CONFIG SET dir "/hardcoded/path/to/your/project/folder"
BGSAVE

(现在,如果您需要将 dump.rdb 文件保存在您启动服务器的目录中,那么您将需要更改该目录的权限,以便 redis 可以写入该目录. 你可以搜索 *** 以了解如何做到这一点)。

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

CONFIG SET dir "./"
BGSAVE

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

【讨论】:

确保授予非 root 用户对存储转储文件的目录的权限。就我而言,我有一个用户 redis,所以我这样做:sudo chown redis:redis /var/lib/redis 非常简单有用的解释【参考方案10】:

遇到了这个错误,并且能够从日志中找出错误是因为磁盘空间不足。不再需要插入到我的案例中的所有数据。所以我试图冲洗。由于 redis-rdb-bgsave 进程正在运行,它也不允许刷新数据。我按照以下步骤操作并能够继续。

    登录redis客户端 执行config set stop-writes-on-bgsave-error no 执行FLUSHALL(不需要存储的数据) 执行config set stop-writes-on-bgsave-error yes

经过上述步骤,进程 redis-rdb-bgsave 不再运行。

【讨论】:

【参考方案11】:

$ redis-cli

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

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

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

你应该做的是:

redis-cli

127.0.0.1:6379> 配置设置目录 /data/tmp 好的 127.0.0.1:6379> 配置集 dbfilename temp.rdb 好的 127.0.0.1:6379> BGSAVE 后台保存开始 127.0.0.1:6379> 请确保 /data/tmp 有足够的磁盘空间。

【讨论】:

如何检查 BGSAVE 命令是否/何时完成?【参考方案12】:

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

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

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

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

另一个解决方案可以是您的系统上运行的其他一些 RAM 重的服务,检查您的服务器/机器/实例上运行的其他服务,如果不需要,请停止它。要检查您机器上运行的所有服务,请使用service --status-all

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

---更新---

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

maxmemory 6gb
maxmemory-policy allkeys-lru

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

【讨论】:

【参考方案13】:

更永久的解决方法可能是在 /etc/redis/redis.conf 中的 200-250 行附近查看 rdb 功能的设置,这些设置在 2.x 时代不是 redis 的一部分。

明显

dir ./

可以改成

dir /home/someuser/redislogfiledirectory

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

还有,别忘了

service redis-server stop
service redis-server start

【讨论】:

停止并开始确实为我修复了它:)【参考方案14】:

对我来说

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

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

【讨论】:

【参考方案15】:

所有这些答案都没有解释 rdb 保存失败的原因。


就我而言,我查看了redis日志,发现:

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

在终端中运行以下命令:

sudo egrep -i -r 'killed process' /var/log/

它显示:

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

就是这样!这个进程(redis save rdb)被OOM killer杀死了

指:

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

Finding which process was killed by Linux OOM killer

【讨论】:

【参考方案16】:

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

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

因此,在闲置一个小时后,如果您以非 root 用户身份运行 redis 容器(例如 docker run -u 1007 而不是默认的 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

所以您需要做的是将容器的/data 文件夹映射到外部位置(非root 用户,此处为:1007,具有写入权限,例如主机上的/tmp),例如:

docker run --rm -d --name redis -p 6379:6379 -u 1007 -v /tmp:/data redis

所以这是官方 docker 镜像的错误配置(应该写给/tmp 而不是/data),它产生了这个“定时炸弹”,你很可能只会在生产中遇到......在一夜之间,在一些特别安静的地方假期周末:/

【讨论】:

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

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

- stop-writes-on-bgsave-error yes
+ stop-writes-on-bgsave-error no

【讨论】:

注意:在 macOS 上,这个文件位于 /usr/local/etc/redis.conf,你需要运行这个命令来重启 redis:brew services restart redis【参考方案18】:

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

【讨论】:

您是如何发现内存溢出问题的?我可能遇到了同样的问题。 @DarthSpeedious 我不记得了。如果我不得不猜测,我会说日志中的某些内容可能在抱怨无法分配内存。抱歉,我不能提供更多帮助。 首先我认为将交换和redis结合使用也是一个很好的解决方案,然后我做了一些研究并找到了这篇文章antirez.com/news/52,它声称这是使用redis的错误方式,反正我不是 100% 同意,你对使用 redis 和 swap 的表现满意吗? @DarthSpeedious 在您的 Redis 日志中,您会看到“无法分配内存”错误。请参阅此处了解如何查看日志文件:***.com/questions/16337107/…【参考方案19】:

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

希望这可以在将来需要时对某人有所帮助。

    检查了 dir 文件夹上的 CHMOD... 发现符号符号有所不同。 CHMOD dir 文件夹到 755 dbfilename 权限很好,无需更改 重新启动redis-server (应该先这样,但是啊)引用redis-server.log,发现错误是访问被拒绝的结果。

再次不确定 DIR 文件夹的权限是如何更改的,但我假设 CHMOD 回到 755 并重新启动 redis-server 处理它,因为之后我能够 ping redis 服务器。

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

【讨论】:

【参考方案20】:

我也面临同样的问题。两个答案(最受支持的一个和接受的一个)都只是给出了一个临时解决方案。

此外,config set stop-writes-on-bgsave-error no 是一种忽略此错误的可怕方法,因为此选项的作用是阻止 redis 通知写入已停止,并继续前进而不将数据写入快照中。这只是忽略了这个错误。 Refer this

关于在redis-cli中设置config中的dir,一旦你重启redis服务,这个也会被清除,同样的错误会再次弹出。 redis.confdir的默认值是./,如果你以root用户启动redis,那么.//,不授予写权限,因此报错。

最好的方法是在 redis.conf 文件中设置dir 参数并对该目录设置适当的权限。大多数 debian 发行版都应该在/etc/redis/redis.conf

【讨论】:

【参考方案21】:

在解决了这么多 SO 问题后终于 - 对我来说@Axel Advento 的回答很有效,但只需几个额外的步骤 - 我仍然面临权限问题。 我不得不将用户切换到redis,在它的主目录中创建一个新目录,然后将其设置为redis的目录。

sudo su - redis -s /bin/bash
mkdir redis_dir
redis-cli CONFIG SET dir $(realpath redis_dir)
exit # to logout from redis user (optional)

【讨论】:

【参考方案22】:

是的,这是因为当前使用没有权限修改“dump.rdb”。

因此,除了创建新的 RDB 文件,您还可以授予旧文件权限(更改它的所有权)。

在redis-cli中输入:

config get dir

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

使用终端转到此位置

cd 
cd /usr/local/var/db

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

sudo chown -R [username] db

这将更改为所有者。

这对我有用。

【讨论】:

【参考方案23】:

如果您使用 docker/docker-compose 并希望阻止 redis 写入文件,您可以创建一个 redis 配置并挂载到容器中

docker.compose.override.yml

  redis:¬
      volumes:¬
        - ./redis.conf:/usr/local/etc/redis/redis.conf¬
      ports:¬
        - 6379:6379¬

您可以从here下载默认配置

确保在 redis.conf 文件中注释掉这 3 行

save 900 1
save 300 10
save 60 10000

你可以查看更多删除持久化数据的解决方案here

【讨论】:

【参考方案24】:

在我的情况下,Ubuntu 虚拟机的磁盘空间已满,这就是我收到此错误的原因。从磁盘中删除一些文件后问题已解决。

【讨论】:

【参考方案25】:

我在具有 AFS 磁盘空间的服务器上工作时遇到了这个问题,因为我的身份验证令牌已过期,当 redis-server 尝试保存时产生了 Permission Denied 响应。我通过刷新我的令牌解决了这个问题:

kinit USERNAME_HERE -l 30d && aklog

【讨论】:

【参考方案26】:

就我而言,这是因为我刚刚使用快速方式安装了redis。所以redis没有以root身份运行。 我能够按照他们的Quick Start Guide 的Installing Redis more properly 部分下的说明解决这个问题。这样做之后,问题就解决了,redis 现在以 root 身份运行。看看吧。

【讨论】:

【参考方案27】:

在采取任何措施之前检查您的 Redis 日志。此线程中的某些解决方案可能会擦除您的 Redis 数据,因此请小心您的操作。

在我的例子中,机器的 RAM 用完了。当主机上没有更多可用磁盘空间时,也会发生这种情况。

【讨论】:

【参考方案28】:

在我的情况下,它与磁盘可用空间有关。 (您可以使用df -h bash 命令检查它)当我释放一些空间时,此错误消失了。

【讨论】:

【参考方案29】:

如果您在 Windows 机器上本地运行 Redis,请尝试“以管理员身份运行”并查看它是否有效。对我来说,问题是 Redis 位于“程序文件”文件夹中,默认情况下会限制权限。应该的。

但是,不要自动以管理员身份运行 Redis 您不想授予它更多应有的权限。你想通过书本解决这个问题。

因此,我们已经能够通过以管理员身份运行它来快速识别问题,但这并不是解决办法。一种可能的情况是,您将 Redis 放在了没有写入权限的文件夹中,因此 DB 文件存储在同一位置。

您可以通过打开redis.windows.conf并搜索以下配置来解决此问题:

    # The working directory.
    #
    # The DB will be written inside this directory, with the filename specified
    # above using the 'dbfilename' configuration directive.
    #
    # The Append Only File will also be created inside this directory.
    #
    # Note that you must specify a directory here, not a file name.
    dir ./

dir ./ 更改为您对其具有常规读/写权限的路径

您也可以将整个 Redis 文件夹移动到您知道具有正确权限的文件夹中。

【讨论】:

【参考方案30】:

请注意,当您的服务器受到攻击时会出现此错误。刚刚发现redis无法写入'/etc/cron.d/web',在更正权限后,添加了由挖掘算法和一些隐藏选项组成的新文件。

【讨论】:

以上是关于MISCONF Redis 配置为保存 RDB 快照的主要内容,如果未能解决你的问题,请参考以下文章