redis クラスタの実装は同じプレフィックスを持つキーをクリーンアップします。
redis クラスタが同じ接頭辞を持つキーのクリーンアップ
最近redisクラスタのアラートが多くて、1日に50通以上来るので、無駄なキー(3000万くらい)がメモリを占有していて、メモリが足りないのが本当に困る(詳細は割愛)。この部分のメモリが解放できないのです。
オリジナルの定期的なクリーンアップスクリプトのロジック
Redisのリンクを開き、内部的に1000万から7億までのデータをループし、一括削除に行くためにプレフィックスを追加し、この方法は、広いキャストネットのクリーンアップに属する、徹底的な方法は、時間がかかるだけでなく、効果的ではありません。
なぜなら、redisに存在しない数字もあるでしょうし、何より7億個以上の数字があると、この部分のデータがクリアされずにスケーラビリティが悪くなってしまうからです。
(1) では、どうやって掃除するのでしょうか?redisクラスタにはキーというメソッドがないので、このキーのバッチを迅速かつ正確に見つけるにはどうしたらいいのでしょうか?
Redis Clusterが提供するgetClusterNodesメソッドでredis-clusterの各ノードを取得し、そのノードのJedisペアを一つずつ取得して、個々のJedisペアで同じプレフィックスのキーを取得すればいいのです
(2) キーセットを取得したら、次にこれらのキーを繰り返し、JedisClusterCRC16.getSlot(key)メソッドでキーがある場所を探し、同じスロット内のキーを一括削除します。これにより、一つ目は削除する必要があるキーがredis cluster内に存在することを確認し、二つ目は一括削除で効率化を図ることができます。
具体的なコード
Map<String, JedisPool> clusterNodes = jedis.getClusterNodes();
String keysPattern = keyPrefix + ":*";
long countX = 0;
long sTime = System.currentTimeMillis();
for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) {
Jedis jedisNode = entry.getValue().getResource();
logger.info("redisip:{},port:{}" , jedisNode.getClient().getHost(), jedisNode.getClient().getPort());
if (!jedisNode.info("replication").contains("role:slave")) {
Set<String> keys = jedisNode.keys(keysPattern);
logger.info("length of keys:{}" , keys.size());
Map<Integer, List<String>> map = new HashMap<>(6600);
long countTmp = 0;
for (String key : keys) { int slot = JedisClusterCRC16.getSlot(key);
/**
* When performing multi-key operations in cluster mode, these keys must be on the same slot.
* otherwise it will report :JedisDataException
* // group the keys by slot, and submit the keys of the same slot together
if (map.containsKey(slot)) {
map.get(slot).add(key);
} else {
List<String> keyList = new ArrayList<String>();
keyList.add(key);
map.put(slot, keyList);
}
}
long count = 0;
for (Map.Entry<Integer, List<String>> integerListEntry : map.entrySet()) {
count += jedisNode.del(integerListEntry.getValue().toArray(new String[integerListEntry.getValue().size()])));
logger.info("Deleted:{} of",count);
countX++;
}
}
}
// logger.info("Deletion complete, total deleted:{}",countX);
logger.info("Deleting userid key task finished, total number of keys deleted:{},time spent:{}", countX , System.currentTimeMillis() - sTime);
redis cluster (jedis) bulk delete same prefix
public Set<String> getByPrefix(String key) {
Set<String> setResult = new HashSet<>();
try {
ShardedJedis jedis = redisDataSource.getJedisClient();
Iterator<Jedis> jedisIterator = jedis.getAllShards().iterator();
while(jedisIterator.hasNext()){
setResult = jedisIterator.next().keys(key+"*");
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return setResult;
}
上記は私の個人的な経験ですが、参考にしていただき、BinaryDevelopをもっとサポートしていただければと思います。
関連
-
redisキャッシュストレージのセッション原理機構
-
Redisによる分散ロック(setnx, getset, incr)の実装とタイムアウトの扱い方
-
Redisの重複排除の3つの手法のまとめ
-
Redisにおけるビットマップの説明
-
ジェディスはRedisを操作してCaptcha配信をシミュレートする
-
Redisデータ永続化技術解説
-
Redisによる携帯電話認証コード配信の模倣例
-
マイクロサービス領域におけるredisの貢献度を説明する
-
SpringBootがRedisの分散ロックを利用して並行処理の問題を解決することについて
-
redis アプリケーション編 ---- スパイク、サインイン、セッション共有
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン