回答:
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
です。or コマンドをLua
実行して、サーバーでこれらのステップを実行するスクリプトを実際に作成できます。この場合も、特定のシナリオでこのアプローチのパフォーマンスを考慮する必要があります。EVAL
EVALSHA
さらにいくつかの参照:
エントリTTLをサポートするハッシュオブジェクトを実装するRedisson JavaフレームワークがありMap
ます。フードの下hmap
でzset
Redisオブジェクトを使用します。使用例:
RMapCache<Integer, String> map = redisson.getMapCache('map');
map.put(1, 30, TimeUnit.DAYS); // this entry expires in 30 days
このアプローチは非常に便利です。
これは、RedisのフォークであるKeyDBで可能です。これはフォークであるため、Redisと完全に互換性があり、代替品として機能します。
EXPIREMEMBERコマンドを使用するだけです。セット、ハッシュ、ソート済みセットで機能します。
EXPIREMEMBER keynameサブキー[時間]
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:*
それがサーバーをブロックしない限り、より良いかもしれません
ここで説明したのと同じ問題がありました。
エントリ(名前/値のペア)をハッシュするキーであるRedisハッシュがあり、各ハッシュエントリの有効期限を個別に保持する必要がありました。
ハッシュエントリの値を書き込むときに、エンコードされた有効期限情報を含むnバイトのプレフィックスデータを追加することでこれを実装し、値が含まれるときにキーが期限切れになるように設定しました。
次に、読み取り時にプレフィックスをデコードし、有効期限を確認します。これは追加のオーバーヘッドですが、読み取りは依然としてO(n)であり、最後のハッシュエントリが期限切れになると、キー全体が期限切れになります。
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を探します)
Redisでソート済みセットを使用して、タイムスタンプをスコアとして持つ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
。