redis에서 "HSET"자식 키를 "EXPIRE"하는 방법은 무엇입니까?


107

1 개월이 지난 redis 해시의 모든 키를 만료시켜야합니다.

답변:


117

이것은 Redis를 단순하게 유지 하기 위해 불가능 합니다 .

Redis의 창시자 Quoth Antirez :

안녕하세요, 해당 특정 필드에 대해 다른 최상위 키를 사용하거나 만료 시간이있는 다른 필드와 함께 저장하고 둘 다 가져 와서 애플리케이션이 여전히 유효한지 여부를 이해하도록하는 것은 불가능합니다. 현재 시간.


8
이것이 redis가 훌륭한 소프트웨어 인 이유입니다. 그들은 간단하게 위치를 알
TOBI

20

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을 실행하여 서버에서 이러한 단계를 수행 하는 스크립트를 실제로 작성할 수 있습니다. 다시 말하지만, 특정 시나리오에 대해이 접근 방식의 성능을 고려해야합니다.EVALEVALSHA

더 많은 참조 :


이 접근 방식은 만료 시간이있는 단순 키보다 더 많은 메모리를 사용합니다.
VasileM

3

엔트리 TTL 지원으로 해시 객체 를 구현 하는 Redisson 자바 프레임 워크가 Map있습니다. 그것은 사용 hmapzset레디 스는 후드 객체. 사용 예 :

RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days

이 접근 방식은 매우 유용합니다.


하지만 어떻게지도를 만들 수 있습니까? 나는 어떤 자습서를 찾을 수없는 또는이 / 설정 방법을 만들 수 있기 때문에
FaNaT

@ ZoltánNémeth Redis에서 첫 번째 값이 삽입되면 자동으로 맵이 생성됩니다.
Nikita Koksharov

3

이것은 Redis의 Fork 인 KeyDB 에서 가능합니다 . Fork이기 때문에 Redis와 완벽하게 호환되며 드롭 인 대체물로 작동합니다.

EXPIREMEMBER 명령을 사용하십시오. 세트, 해시 및 정렬 된 세트와 함께 작동합니다.

EXPIREMEMBER 키 이름 하위 키 [시간]

TTL 및 PTTL을 사용하여 만료를 확인할 수도 있습니다.

TTL 키 이름 하위 키

https://docs.keydb.dev/docs/commands/#expiremember 에서 더 많은 문서를 사용할 수 있습니다.


2

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)단일 호출 로 전달 하면이 작업을보다 효율적으로 수행 할 수 있습니다 .
doublesharp

const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
doublesharp

1

할 수 있습니다. 여기에 예가 있습니다.

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

사용 EXPIRE 또는 EXPIREAT 명령을 .

1 개월이 지난 해시의 특정 키를 만료하려는 경우. 이건 불가능 해. Redis expire 명령은 해시의 모든 키에 대한 것입니다. 일일 해시 키를 설정하면 키 수명을 설정할 수 있습니다.

hset key-20140325 f1 1
expire key-20140325 100
hset key-20140325 f1 2

24
나는 그가 해시의 모든 키 를 만료하기를 원하지 않는다고 생각 합니다. 오히려 해시의 모든 키가 1 개월 이상 이므로 일부만 만료됩니다 . 어떤 AFAIK가 불가능합니다.
UpTheCreek

1
IMHO 질문은 우리가 이것을 가정하게합니다. 그래서 조나단은 나에게서 +1을받습니다. 그가 나를 도왔 기 때문입니다! 고맙습니다!
longliveenduro 2011

"f1"과 "f2"는 어떻게 만료됩니까?
vgoklani

4
이것은 질문에 대한 답이 아니거나 전혀 도움이되지 않습니다. 해시 자체가 아니라 해시의 요소를 만료해야합니다.
Ron

@UpTheCreek 감사합니다!
조나단 김

1

이를 위해 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


1
바로이 성능 특성에 상당한 변화 인식
다니엘 파렐

어떻게! 당신은 시간의 복잡성에 대해 이야기하면,이 모든 작업은 같은 시간 복잡도가 hashset.. GET O (1) 세트 O (1) 모든 O (n)을 얻을
무하마드 솔리

"KEYS는 극도의주의를 기울여 프로덕션 환경에서만 사용해야하는 명령으로 생각하십시오." redis.io/commands/KEYS . HGETALL은 O(n)세트 KEYS의 사물 수, DB의 사물 수입니다.
Daniel Farrell

사실 그, scan 0 match namespace:*더 오래가 서버 차단하지 않는 한있을 수 있습니다
무하마드 솔리

1
또한 이러한 키가 작은 경우 다른 데이터베이스로 분리하십시오. 덕분에 @DanFarrell
무하마드 솔리에게

1

우리는 여기에서 동일한 문제를 논의했습니다.

Redis 해시, 해시 항목 (이름 / 값 쌍)에 대한 키가 있으며 각 해시 항목에 대해 개별 만료 시간을 유지해야했습니다.

해시 항목 값을 쓸 때 인코딩 된 만료 정보를 포함하는 n 바이트의 접두사 데이터를 추가하여이를 구현했으며, 기록되는 값에 포함 된 시간에 만료되도록 키도 설정했습니다.

그런 다음 읽을 때 접두사를 디코딩하고 만료 여부를 확인합니다. 이는 추가 오버 헤드이지만 읽기는 여전히 O (n)이며 마지막 해시 항목이 만료되면 전체 키가 만료됩니다.


0

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 플래그 찾기)


0

redis에서 Sorted Set 를 사용 하여 타임 스탬프를 점수로 사용하는 TTL 컨테이너를 가져올 수 있습니다 . 예를 들어, 이벤트 문자열을 세트에 삽입 할 때마다 해당 점수를 이벤트 시간으로 설정할 수 있습니다. 따라서 호출하여 모든 시간 창의 데이터를 얻을 수 있습니다. zrangebyscore "your set name" min-time max-time

또한을 사용 zremrangebyscore "your set name" min-time max-time하여 오래된 이벤트를 제거 하여 만료시킬 수 있습니다.

여기서 유일한 단점은 세트의 크기를 유지하기 위해 외부 프로세스에서 하우스 키핑을 수행해야한다는 것입니다.


-1

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)

6
질문은 hset전체가 아닌 만료 자식 에 관한 것 hset입니다.
thangdc94

묻는 질문에 대답하지 않습니다
peteclark3
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.