redis에서 "HSET"자식 키를 "EXPIRE"하는 방법은 무엇입니까?
1 개월이 지난 redis 해시의 모든 키를 만료시켜야합니다.
이것은 Redis를 단순하게 유지 하기 위해 불가능 합니다 .
Redis의 창시자 Quoth Antirez :
안녕하세요, 해당 특정 필드에 대해 다른 최상위 키를 사용하거나 만료 시간이있는 다른 필드와 함께 저장하고 둘 다 가져 와서 애플리케이션이 여전히 유효한지 여부를 이해하도록 할 수 없습니다. 현재 시간.
Redis는 TTL
전체 해시를 만료시키는 최상위 키 이외의 해시 사용을 지원하지 않습니다 . 샤딩 된 클러스터를 사용하는 경우 사용할 수있는 다른 접근 방식이 있습니다. 이 접근 방식은 모든 시나리오에서 유용 할 수는 없으며 성능 특성이 예상되는 것과 다를 수 있습니다. 여전히 언급 할 가치가있는 :
해시가있을 때 구조는 기본적으로 다음과 같습니다.
hash_top_key
- child_key_1 -> some_value
- child_key_2 -> some_value
...
- child_key_n -> some_value
TTL
자식 키 에 추가하고 싶기 때문에 상위 키로 이동할 수 있습니다. 요점은 이제 키가 hash_top_key
와 자식 키 의 조합이어야한다는 것입니다 .
{hash_top_key}child_key_1 -> some_value
{hash_top_key}child_key_2 -> some_value
...
{hash_top_key}child_key_n -> some_value
우리는 {}
의도적으로 표기법을 사용하고 있습니다. 이렇게하면 모든 키가 동일하게 떨어 hash slot
집니다. https://redis.io/topics/cluster-tutorial 에서 자세한 내용을 읽을 수 있습니다.
이제 동일한 해시 작업을 수행하려면 다음을 수행 할 수 있습니다.
HDEL hash_top_key child_key_1 => DEL {hash_top_key}child_key_1
HGET hash_top_key child_key_1 => GET {hash_top_key}child_key_1
HSET hash_top_key child_key_1 some_value => SET {hash_top_key}child_key_1 some_value [some_TTL]
HGETALL hash_top_key =>
keyslot = CLUSTER KEYSLOT {hash_top_key}
keys = CLUSTER GETKEYSINSLOT keyslot n
MGET keys
여기서 흥미로운 것은입니다 HGETALL
. 먼저 우리 hash slot
는 모든 자녀 키를 얻습니다 . 그런 다음 특정 키를 얻고 hash slot
마지막으로 값을 검색합니다. 여기에주의해야 n
합니다. hash slot
그에 대한 키 보다 더 많은 키 가있을 수 있고 우리가 관심을 갖지 않지만 동일한 키를 가질 수도 있기 때문 hash slot
입니다. 또는 명령 Lua
을 실행하여 서버에서 이러한 단계를 수행 하는 스크립트를 실제로 작성할 수 있습니다. 다시 말하지만, 특정 시나리오에 대해이 접근 방식의 성능을 고려해야합니다.EVAL
EVALSHA
더 많은 참조 :
- https://redis.io/commands/cluster-keyslot
- https://redis.io/commands/cluster-getkeysinslot
- https://redis.io/commands/eval
There is a Redisson java framework which implements hash Map
object with entry TTL support. It uses hmap
and zset
Redis objects under the hood. Usage example:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
This approach is quite useful.
Regarding a NodeJS implementation, I have added a custom expiryTime
field in the object I save in the HASH. Then after a specific period time, I clear the expired HASH entries by using the following code:
client.hgetall(HASH_NAME, function(err, reply) {
if (reply) {
Object.keys(reply).forEach(key => {
if (reply[key] && JSON.parse(reply[key]).expiryTime < (new Date).getTime()) {
client.hdel(HASH_NAME, key);
}
})
}
});
You could store key/values in Redis differently to achieve this, by just adding a prefix or namespace to your keys when you store them e.g. "hset_"
Get a key/value
GET hset_key
equals toHGET hset key
Add a key/value
SET hset_key value
equals toHSET hset key
Get all keys
KEYS hset_*
equals toHGETALL hset
Get all vals should be done in 2 ops, first get all keys
KEYS hset_*
then get the value for each keyAdd a key/value with TTL or expire which is the topic of question:
SET hset_key value
EXPIRE hset_key
Note: KEYS
will lookup up for matching the key in the whole database which may affect on performance especially if you have big database.
Note:
KEYS
will lookup up for matching the key in the whole database which may affect on performance especially if you have big database. whileSCAN 0 MATCH hset_*
might be better as long as it doesn't block the server but still performance is an issue in case of big database.You may create a new database for storing separately these keys that you want to expire especially if they are small set of keys.
Thanks to @DanFarrell who highlighted the performance issue related to
KEYS
You can. Here is an example.
redis 127.0.0.1:6379> hset key f1 1
(integer) 1
redis 127.0.0.1:6379> hset key f2 2
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> expire key 10
(integer) 1
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key
1) "1"
2) "1"
3) "2"
redis 127.0.0.1:6379> hvals key
Use EXPIRE or EXPIREAT command.
If you want to expire specific keys in the hash older then 1 month. This is not possible. Redis expire command is for all keys in the hash. If you set daily hash key, you can set a keys time to live.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
You can expire Redis hashes in ease, Eg using python
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
This will expire all child keys in hash hashed_user after 10 seconds
same from redis-cli,
127.0.0.1:6379> HMSET testt username wlc password P1pp0 age 34
OK
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
127.0.0.1:6379> expire testt 10
(integer) 1
127.0.0.1:6379> hgetall testt
1) "username"
2) "wlc"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
after 10 seconds
127.0.0.1:6379> hgetall testt
(empty list or set)
You could use the Redis Keyspace Notifications by using psubscribe
and "__keyevent@<DB-INDEX>__:expired"
.
With that, each time that a key will expire, you will get a message published on your redis connection.
Regarding your question basically you create a temporary "normal" key using set
with an expiration time in s/ms. It should match the name of the key that you wish to delete in your set.
As your temporary key will be published to your redis connection holding the "__keyevent@0__:expired"
when it expired, you can easily delete your key from your original set as the message will have the name of the key.
A simple example in practice on that page : https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc : https://redis.io/topics/notifications ( look for the flag xE)
You can use Sorted Set in redis to get a TTL container with timestamp as score. For example, whenever you insert a event string into the set you can set its score to the event time. Thus you can get data of any time window by calling zrangebyscore "your set name" min-time max-time
Moreover, we can do expire by using zremrangebyscore "your set name" min-time max-time
to remove old events.
The only drawback here is you have to do housekeeping from an outsider process to maintain the size of the set.
We had the same problem discussed here.
We have a Redis hash, a key to hash entries (name/value pairs), and we needed to hold individual expiration times on each hash entry.
We implemented this by adding n bytes of prefix data containing encoded expiration information when we write the hash entry values, we also set the key to expire at the time contained in the value being written.
Then, on read, we decode the prefix and check for expiration. This is additional overhead, however, the reads are still O(n) and the entire key will expire when the last hash entry has expired.
참고URL : https://stackoverflow.com/questions/16545321/how-to-expire-the-hset-child-key-in-redis
'developer tip' 카테고리의 다른 글
Java에서 클래스 불변이란 무엇입니까? (0) | 2020.09.22 |
---|---|
PUT 및 DELETE HTTP 요청 방법의 유용성은 무엇입니까? (0) | 2020.09.22 |
git push origin HEAD는 무엇을 의미합니까? (0) | 2020.09.22 |
Ruby의 다른 괄호는 무엇을 의미합니까? (0) | 2020.09.22 |
다른 모듈에서 모듈 변수를 변경하는 방법은 무엇입니까? (0) | 2020.09.22 |