redis - Redis 中的模式迁移

标签 redis

我有一个使用 redis 的应用程序。我使用了键名 user:<id>存储用户信息。然后在本地我更改了我的应用程序代码以使用 key 名称 user:<id>:data为此目的。

我害怕如果我将这个新代码推送到我的生产服务器,事情就会崩溃。这样做的原因是因为我的生产 redis 服务器已经有了 key ,这些 key 将是旧的 key 名称。

所以我认为唯一的方法是停止我的应用程序,将所有旧的 key 名称更改为新名称,然后重新启动它。你有更好的选择吗?感谢您的帮助:)

最佳答案

将新代码推送到您的生产环境始终是一项令人恐惧的工作(这就是为什么只有最艰难的人才能在这个行业中生存;))。我强烈建议您在更改生产代码和数据库之前,确保在本地测试工作流及其结果。

几乎所有对应用程序的更新都需要停止 - 即使只是为了替换相关文件。正是由于您提到的原因,对于涉及数据库的任何更改更是如此。

即使您可以在不停止应用程序本身(例如 PHP 页面)的情况下部署代码更改,您仍然希望数据库更改“自动”完成 - 即没有任何应用程序请求干预和可能中断。虽然某些数据库可以脱机进行维护,但即使这样您通常也会停止应用程序,否则会在各处产生错误。

如果情况确实如此,您将停止该应用程序(或将其置于维护模式),而不管数据库是否发生变化,因此我们将您的问题实际理解为:重命名所有/某些键的最快方法是什么在我的数据库中?

为了回答这个问题,与上面建议的伪代码类似,我建议您使用如下所示的 Lua 脚本,并在您停止应用程序后对它进行 EVAL:

for _,k in ipairs(redis.call('keys', 'user:*')) do 
    if k:sub(-5) ~= ':data' then 
        redis.call('rename', k, k .. ':data')
    end
end

关于此脚本的一些注意事项您应该牢记:

  1. 虽然 KEYS 命令在生产中使用不安全,但由于您正在进行维护,因此可以安全使用它。对于需要扫描 key 的所有其他用例,Redis 的 SCAN 更为可取。

  2. 由于 Lua 脚本是“原子的”,理论上您可以在不停止应用程序的情况下运行此脚本 - 只要脚本在运行(这取决于您的数据集的大小),应用程序的请求就会被阻止。换句话说,这种方法解决了获得混合键名(旧的和新的)的问题。然而,这可能不是您在任何情况下都想做的,因为 a) 您的应用程序在那段时间可能仍然会出错/超时,但主要是因为 b) 它需要能够处理两种类型的键名(即使用旧 key 运行 -> 短/长暂停 -> 使用新 key 运行)使您的代码更加复杂。

  3. 如果您打算只运行一次脚本并成功,则不需要 if 条件。

  4. 根据您数据库的实际内容,您可能希望进一步过滤掉不应重命名的键。

  5. 为确保兼容性,避免硬编码/计算生成 key 名称 - 相反,它们应作为参数传递给脚本。

关于redis - Redis 中的模式迁移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21499149/

相关文章:

Redis:查找与某些模式匹配的键

redis - 安装 Celery/Redis 以在另一台服务器上运行任务的正确方法是什么?

java - RedisTemplate 保存多个键值对到哈希问题

node.js - 使用 Socket.io 和 Redis 的 Node 集群问题

python - 使用 Flask 获取 int 列表并将这些值作为端点返回

sql-server - 具有 Pub/Sub OnChange 的持久性 DataCache

python - 如何让redis缓存和mysql的数据保持一致?

graph - Tinkerpop - 使用 Redis 进行键值属性索引更好还是使用 KeyIndexableGraph

python - Redis 对象映射器的原子事务?

redis - Redis 中的事务 - 另一个数据库中的读取操作