dragonflydb / dragonfly

A modern replacement for Redis and Memcached
https://www.dragonflydb.io/
Other
25.8k stars 948 forks source link

Redis API incompatibility on `SET` command modifying key with an expiration #607

Closed ported-pw closed 1 year ago

ported-pw commented 1 year ago

Describe the bug In Redis, a key that has an expiry set, can be overwritten without any issues. In Dragonfly, if a key has an expiry added, the SET command does not replace the value but still returns OK and wipes the expiry time.

To Reproduce Steps to reproduce the behavior:

  1. Set a key with SET key value
  2. GET the key, observe it being set correctly
  3. Set the same key, replacing the value with SET key value1
  4. GET the key, observe it still being set correctly
  5. Add an expiry to the key with EXPIRE key seconds
  6. Set the same key, replacing the value with SET key value2
  7. GET the key, observe the key not being updated and still being value1
  8. After seconds set in 5., GET the key and observe it still existing (meaning that SET did remove the expiry)

Expected behavior The key should be updated and the expiry cleared regardless of expiry or current value. Quoting the Redis docs for the SET command:

Set key to hold the string value. If key already holds a value, it is overwritten, regardless of its type. Any previous time to live associated with the key is discarded on successful SET operation.

Environment (please complete the following information):

Reproducible Code Snippet On Dragonfly:

127.0.0.1:36379> set hello world
OK
127.0.0.1:36379> get hello
"world"
127.0.0.1:36379> set hello world1
OK
127.0.0.1:36379> get hello
"world1"
127.0.0.1:36379> expire hello 100
(integer) 1
127.0.0.1:36379> set hello world2
OK
127.0.0.1:36379> get hello
"world1"

On Redis 7.0.7:

127.0.0.1:26379> set hello world
OK
127.0.0.1:26379> get hello
"world"
127.0.0.1:26379> set hello world1
OK
127.0.0.1:26379> get hello
"world1"
127.0.0.1:26379> expire hello 100
(integer) 1
127.0.0.1:26379> set hello world2
OK
127.0.0.1:26379> get hello
"world2"
romange commented 1 year ago

Thanks for reporting this issue. It will be fixed with the next release.

On Mon, Dec 26, 2022, 21:07 ported-pw @.***> wrote:

Describe the bug In Redis, a key that has an expiry set, can be overwritten without any issues. In Dragonfly, if a key has an expiry added, the SET command does not replace the value but still returns OK.

To Reproduce Steps to reproduce the behavior:

  1. Set a key with SET key value
  2. GET the key, observe it being set correctly
  3. Set the same key, replacing the value with SET key value1
  4. GET the key, observe it still being set correctly
  5. Add an expiry to the key with EXPIRE key seconds
  6. Set the same key, replacing the value with SET key value2
  7. GET the key, observe the key not being updated and still being value1

Expected behavior The key should be updated and the expiry cleared regardless of expiry or current value. Quoting the Redis docs for the SET command https://redis.io/commands/set/:

Set key to hold the string value. If key already holds a value, it is overwritten, regardless of its type. Any previous time to live associated with the key is discarded on successful SET operation.

Environment (please complete the following information):

  • OS: Host: Ubuntu 22.04 (Pop!OS) for this example, also AlmaLinux 9 in Production
  • Kernel: Linux pop-os 6.1.0-x64v1-xanmod1 #0~20221213.629e4bb9 SMP PREEMPT_DYNAMIC Tue Dec 13 11:05:44 UTC x86_64 x86_64 x86_64 GNU/Linux (for this example), Linux [redacted] 5.14.0-70.26.1.el9_0.x86_64 #1 SMP PREEMPT Tue Sep 20 08:44:24 EDT 2022 x86_64 x86_64 x86_64 GNU/Linux in Production
  • Containerized?: Yes, Docker for this example, also Kubernetes in Production
  • Dragonfly Version: v0.12.0

Reproducible Code Snippet On Dragonfly:

127.0.0.1:36379> set hello world OK127.0.0.1:36379> get hello "world"127.0.0.1:36379> set hello world1 OK127.0.0.1:36379> get hello "world1"127.0.0.1:36379> expire hello 100 (integer) 1127.0.0.1:36379> set hello world2 OK127.0.0.1:36379> get hello "world1"

On Redis 7.0.7:

127.0.0.1:26379> set hello world OK127.0.0.1:26379> get hello "world"127.0.0.1:26379> set hello world1 OK127.0.0.1:26379> get hello "world1"127.0.0.1:26379> expire hello 100 (integer) 1127.0.0.1:26379> set hello world2 OK127.0.0.1:26379> get hello "world2"

— Reply to this email directly, view it on GitHub https://github.com/dragonflydb/dragonfly/issues/607, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4BFCGHMGQYAOVACY42OPDWPHUGNANCNFSM6AAAAAATJ2YACQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

romange commented 1 year ago

@ported-pw the fixed version is released.