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 服务器。
macOS (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 redis
和brew 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_status
是ok
。之后,您现在可以开始将生成的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 在他的评论中提到的那样:“忽略这些错误看起来并不酷。”
---更新---
您还可以配置maxmemory
和maxmemory-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.conf
中dir
的默认值是./
,如果你以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 快照的主要内容,如果未能解决你的问题,请参考以下文章