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です。or コマンドをLua実行して、サーバーでこれらのステップを実行するスクリプトを実際に作成できます。この場合も、特定のシナリオでこのアプローチのパフォーマンスを考慮する必要があります。EVALEVALSHA

さらにいくつかの参照:


このアプローチは、有効期限付きの単純なキーよりも多くのメモリを使用します。
VasileM

3

エントリTTLをサポートするハッシュオブジェクトを実装するRedisson JavaフレームワークがありMapます。フードの下hmapzsetRedisオブジェクトを使用します。使用例:

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

このアプローチは非常に便利です。


しかし、どうすれば地図を作成できますか?チュートリアルも作成/設定メソッドも見つからないため
FaNaT

@ZoltánNémethRedisマップでは、最初の値が挿入されたときに自動的に作成されます。
Nikita Koksharov

3

これは、RedisのフォークであるKeyDBで可能です。これはフォークであるため、Redisと完全に互換性があり、代替品として機能します。

EXPIREMEMBERコマンドを使用するだけです。セット、ハッシュ、ソート済みセットで機能します。

EXPIREMEMBER keynameサブキー[時間]

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)単一の呼び出しで渡すことにより、これをより効率的にすることができます。
ダブルシャープ

const keys = Object.keys(reply).filter(key => reply[key] && JSON.parse(reply[key]).expiryTime < Date.now()); client.hdel(HASH_NAME, ...keys);
ダブルシャープ

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 2013

1
私見の質問では、これを仮定します。したがって、ジョナサンは私から+1を受け取ります。ありがとう!
longliveenduro

「f1」と「f2」をどのように期限切れにしますか?
vgoklani 2013

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
これはパフォーマンス特性の大幅な変更であることを認識してください
Daniel Farrell

どうやって!時間の複雑さについて話すと、これらのすべての操作はhashset.. get O(1)と同じ時間の複雑さを持っています。O(1)はすべてO(n)を取得します
Muhammad Soliman

「KEYSは、実稼働環境でのみ細心の注意を払って使用するコマンドとして検討してください。」 redis.io/commands/KEYS。HGETALLはO(n)、セットKEYS内のものの数、DB内のものの数です。
ダニエル・ファレル

それは本当です、scan 0 match namespace:*それがサーバーをブロックしない限り、より良いかもしれません
Muhammad Soliman

1
また、これらのキーが小さいセットの場合は、別のデータベースに分離します。ありがとう@DanFarrell
ムハンマドソリマン

1

ここで説明したのと同じ問題がありました。

エントリ(名前/値のペア)をハッシュするキーであるRedisハッシュがあり、各ハッシュエントリの有効期限を個別に保持する必要がありました。

ハッシュエントリの値を書き込むときに、エンコードされた有効期限情報を含むnバイトのプレフィックスデータを追加することでこれを実装し、値が含まれるときにキーが期限切れになるように設定しました。

次に、読み取り時にプレフィックスをデコードし、有効期限を確認します。これは追加のオーバーヘッドですが、読み取りは依然としてO(n)であり、最後のハッシュエントリが期限切れになると、キー全体が期限切れになります。


0

psubscribeおよびを使用して、Redisキースペース通知を使用できます"__keyevent@<DB-INDEX>__:expired"

これにより、キーの有効期限が切れるたびに、redis接続でメッセージが公開されます。

あなたの質問に関しては、基本的にset、有効期限を秒/ミリ秒で使用して一時的な「通常の」キーを作成します。セット内で削除するキーの名前と一致する必要があります。

一時キーは期限切れのを保持しているredis接続に公開"__keyevent@0__:expired"されるため、メッセージにはキーの名前が含まれるため、元のセットからキーを簡単に削除できます。

そのページの実際の簡単な例:https : //medium.com/@micah1powell/using-redis-keyspace-notifications-for-a-reminder-service-with-node-c05047befec3

doc:https : //redis.io/topics/notifications(フラグxEを探します)


0

Redisでソート済みセットを使用して、タイムスタンプをスコアとして持つ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.