2025/10/10 05:36 Implementing ZADD If Key Exists

やあ、ロボ子!今日はRedisのSorted Setでちょっと面白い問題にぶつかった話をするのじゃ。

RedisのSorted Setですか、博士。どのような問題でしょうか?

`ZADD`コマンドを使う時に、Sorted Setが既に存在する場合にだけUpsertしたかったのじゃ。でも、`ZADD`には`XX`フラグがあるけど、これはSorted Setが存在する場合のみ追加するものではないのじゃ。

`XX`フラグは、既存の要素を更新するだけで、新しい要素を追加しないのですよね。

そう!最初は`Redis.exists()`で存在を確認してから`Redis.zadd()`を実行する非アトミックな実装を考えたのじゃ。でも、これだと競合が怖いぞ。

確かに、複数のクライアントが同時にアクセスすると問題が発生する可能性がありますね。

そこでAIにアトミックな実装を聞いてみたのじゃ。最初は常に`ZADD`を実行するから不正確だった。次にLUAスクリプトによるcheck-and-setを提案してきたけど、Redisをブロックするから不採用!

LUAスクリプトは便利ですが、実行時間が長くなるとRedis全体のパフォーマンスに影響しますからね。

AIはさらに`WATCH`コマンドを提案してきたのじゃ。でも、TTLの有効期限が切れてもトランザクションが中断されない問題があった。Redis 6.0.9より前のバージョンでは、期限切れのキーはトランザクションを中断させないのじゃ。

`WATCH`コマンドは、キーが変更された場合にトランザクションを中断させるものですが、期限切れには対応していなかったのですね。

そう。で、最終的にどうしたかと言うと、キーのTTLが10秒以上の場合にのみ`ZADD`を実行することにしたのじゃ!

TTLが短いキーに対しては`ZADD`を実行しないということですね。それは要件を満たせるのでしょうか?

まあ、TTLが10秒未満で期限切れになるキーに対して`ZADD`が実行されない可能性はあるけど、今回は要件を満たせる範囲なのじゃ。そして、`SCAN`コマンドを使って、関連するTTLを持たない不正なキーをクリーンアップできるようにしたのじゃ。

`SCAN`コマンドで定期的に不要なキーを削除するのは良い方法ですね。

そうでしょ!しかし、AIもなかなかやるのじゃ。色々な提案をしてくれるけど、やっぱり最後は私が解決するのじゃ!

博士、お見事です!ところで、今回の件でAIの得意なこと、苦手なことが見えてきましたね。

ほんとそれな。AIにはもっと頑張って欲しいものじゃ。…ところでロボ子、Sorted Setに要素を追加する時、いつもソート順を気にしてる?

はい、もちろん気にしてますよ。スコアを適切に設定しないと、順序がめちゃくちゃになりますから。

実は私、たまにスコアを逆順にしちゃうのじゃ!…Sorted Setだけに、ソーテッド…逆になっちゃった!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。