답변:
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
더 많은 참조 :
엔트리 TTL 지원으로 해시 객체 를 구현 하는 Redisson 자바 프레임 워크가 Map
있습니다. 그것은 사용 hmap
및 zset
레디 스는 후드 객체. 사용 예 :
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
이 접근 방식은 매우 유용합니다.
이것은 Redis의 Fork 인 KeyDB 에서 가능합니다 . Fork이기 때문에 Redis와 완벽하게 호환되며 드롭 인 대체물로 작동합니다.
EXPIREMEMBER 명령을 사용하십시오. 세트, 해시 및 정렬 된 세트와 함께 작동합니다.
EXPIREMEMBER 키 이름 하위 키 [시간]
TTL 및 PTTL을 사용하여 만료를 확인할 수도 있습니다.
TTL 키 이름 하위 키
https://docs.keydb.dev/docs/commands/#expiremember 에서 더 많은 문서를 사용할 수 있습니다.
NodeJS 구현과 관련 expiryTime
하여 HASH에 저장 한 객체에 사용자 정의 필드를 추가했습니다 . 그런 다음 특정 기간이 지난 후 다음 코드를 사용하여 만료 된 HASH 항목을 지 웁니다.
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);
}
})
}
});
Array.filter
배열을 keys
만든 다음 client.hdel(HASH_NAME, ...keys)
단일 호출 로 전달 하면이 작업을보다 효율적으로 수행 할 수 있습니다 .
const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
할 수 있습니다. 여기에 예가 있습니다.
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
1 개월이 지난 해시의 특정 키를 만료하려는 경우. 이건 불가능 해. Redis expire 명령은 해시의 모든 키에 대한 것입니다. 일일 해시 키를 설정하면 키 수명을 설정할 수 있습니다.
hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2
이를 위해 Redis에 키 / 값을 다르게 저장할 수 있습니다. 예를 들어 "hset_"와 같이 키를 저장할 때 키에 접두사 또는 네임 스페이스를 추가하면됩니다.
다음과 같은 키 / 값 가져 GET hset_key
오기HGET hset key
키를 추가 / 값 SET hset_key value
에 동일HSET hset key
다음과 같은 모든 키 가져 KEYS hset_*
오기HGETALL hset
모든 KEYS hset_*
값 가져 오기는 2 개의 작업으로 수행되어야하며 먼저 모든 키를 가져온 다음 각 키의 값을 가져옵니다.
TTL을 사용 하여 키 / 값을 추가 하거나 문제의 주제 인 만료 :
SET hset_key value
EXPIRE hset_key
참고 : KEYS
특히 큰 데이터베이스가있는 경우 성능에 영향을 미칠 수있는 전체 데이터베이스에서 키와 일치하는지 검색합니다.
노트 :
KEYS
특히 큰 데이터베이스가있는 경우 성능에 영향을 미칠 수있는 전체 데이터베이스에서 키와 일치하는지 검색합니다. 동안은 SCAN 0 MATCH hset_*
이 서버를 차단하지 않습니다하지만 여전히 성능이 큰 데이터베이스의 경우 문제는만큼 더 좋을 수 있습니다.
특히 작은 키 집합 인 경우 만료하려는 이러한 키를 별도로 저장하기 위해 새 데이터베이스를 만들 수 있습니다.
관련 성능 문제를 강조한 @DanFarrell에게 감사드립니다.
KEYS
hashset
.. GET O (1) 세트 O (1) 모든 O (n)을 얻을
O(n)
세트 KEYS
의 사물 수, DB의 사물 수입니다.
scan 0 match namespace:*
더 오래가 서버 차단하지 않는 한있을 수 있습니다
psubscribe
및을 사용하여 Redis Keyspace 알림을 사용할 수 있습니다 "__keyevent@<DB-INDEX>__:expired"
.
이를 통해 키가 만료 될 때마다 redis 연결에 게시 된 메시지를 받게됩니다.
귀하의 질문에 대해서는 기본적으로 다음을 사용하여 임시 "일반"키를 만듭니다. set
s / ms 단위의 만료 시간을 . 세트에서 삭제하려는 키의 이름과 일치해야합니다.
임시 키가 "__keyevent@0__:expired"
만료 될 때를 보유한 redis 연결에 게시 되므로 메시지에 키 이름이 있으므로 원래 세트에서 키를 쉽게 삭제할 수 있습니다.
해당 페이지의 실제 사례 : https://medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3
doc : https://redis.io/topics/notifications (xE 플래그 찾기)
redis에서 Sorted Set 를 사용 하여 타임 스탬프를 점수로 사용하는 TTL 컨테이너를 가져올 수 있습니다 . 예를 들어, 이벤트 문자열을 세트에 삽입 할 때마다 해당 점수를 이벤트 시간으로 설정할 수 있습니다. 따라서 호출하여 모든 시간 창의 데이터를 얻을 수 있습니다.
zrangebyscore "your set name" min-time max-time
또한을 사용 zremrangebyscore "your set name" min-time max-time
하여 오래된 이벤트를 제거 하여 만료시킬 수 있습니다.
여기서 유일한 단점은 세트의 크기를 유지하기 위해 외부 프로세스에서 하우스 키핑을 수행해야한다는 것입니다.
Redis 해시를 쉽게 만료 할 수 있습니다 ( 예 : Python 사용).
import redis
conn = redis.Redis('localhost')
conn.hmset("hashed_user", {'name': 'robert', 'age': 32})
conn.expire("hashed_user", 10)
이것은 모든 만료 아이 키 의 해시 hashed_user을 10 초 후에
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"
10 초 후
127.0.0.1:6379> hgetall testt
(empty list or set)
hset
전체가 아닌 만료 자식 에 관한 것 hset
입니다.