Redis notifications: Get key and value on expiration

后端 未结 3 425
清酒与你
清酒与你 2021-01-30 14:45

we have the following use case: Every time a certain key expires, we need to get notified and do something, based on it\'s value. But when redis fires the expired e

3条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-30 15:20

    The feature that Eli linked to allows you to listen when a key expires. However, it does not give you the value of the key. Futhermore, based on the filed github issue it does not look like you can expect to have this feature built in anytime soon if ever (https://github.com/antirez/redis/issues/1876). The solution I use is to create a special "shadow" expiration key that is linked to the key where you have an actual value.

    So lets say you have a key called testkey and it has an integer value of 100. Furthermore, the key will expire after 10 seconds at which point you want to get the value of the key. (Maybe you were incrementing the key during the 10 seconds it existed).

    First you need to setup listening for keyspace events. In particular you want to listen for expired events. You can do this from your config or use the config set command in redis. (see here for more info: http://redis.io/topics/notifications)

    CONFIG SET notify-keyspace-events Ex
    

    Now you can subscribe to a special keyevent channel where you will be notified that the key expired.

    SUBSCRIBE __keyevent@0__:expired
    

    The format of the channel to subscribe to is __keyevent@__:. In our example we're assuming we're working with the default database 0 and we want to listen for the expired event.

    When the testkey expires you will now get a message in the __keyevent__ channel where the message is the name of the key that expired. Of course at this point the key is gone so we can no longer access the value! The solution is to use a special expiration key.

    When you create your testkey also create a special expiring "shadow" key (don't expire the actual testkey). For example:

    SET testkey 100
    SET shadowkey:testkey "" EX 10
    

    Now in the __keyevent@0__:expired channel you will get a message telling you that the key shadowkey:testkey expired. Take the value of the message (which is the name of the key), split on the colon (or whatever separator you decide to use), and then manually get the value of the key and delete it.

    // set your key value
    SET testkey 100 
    //set your "shadow" key, note the value here is irrelevant
    SET shadowkey:testkey "" EX 10 
    // Get an expiration message in the channel __keyevent@0__:expired
    // Split the key on ":", take the second part to get your original key
    // Then get the value and do whatever with it
    GET testkey
    // Then delete the key
    DEL testkey
    

    Note that the value of the shadowkey isn't used so you want to use the smallest possible value which according to this answer (Redis store key without a value) is an empty string "". It's a little more work to setup but the above system does exactly what you need. The overhead is a few extra commands to actually retrieve and delete your key plus the storage cost of an empty key.

提交回复
热议问题