Redis4.0は(指定された要素の型キーの主に大規模なコレクション)リスクに対処し、非常に便利な怠惰な無料の特性を追加して根本的にビッグキーを削除しました。著者Redisの運用・保守ももたらした可用性とパフォーマンスの問題を削除するには、いくつかのビッグキーに遭遇します。
この記事は、次のセクションに分かれて自由な怠惰のRedisについて説明します。
- 怠惰な自由定義
- なぜ我々は怠惰な自由が必要なのか
- 怠惰な自由を使用してください
- 怠け者無料モニター
- 怠惰な自由を達成するための簡単な分析
怠惰な自由定義
怠惰な遊離は、不活性または遅延放出を削除するように変換することができる。場合削除キー、削除減少、個々のサブスレッドを処理する非同期遅延放出Redisのメモリ機能キー、バイオにおける離鍵操作(バックグラウンドI / O)を提供メインスレッドをブロックするためのRedisの大きなキー。効果的に大きなキーによるパフォーマンスと可用性の問題を取り除くことは避けてください。
なぜ我々は怠惰な自由が必要なのか
Redisのは(バイオタスクの少量を除く)、シングルスレッドプログラムで、すべてのキューに入れられた要求は、パフォーマンスの問題、またはフェールオーバークラスターのさえ発生を引き起こし、他の要求に応答しないRedisの原因となる大きな消費要求を実行しているとき。
Redisのキーの大規模なコレクションを削除する場合や、要求時間がかかるのこのタイプに属します。百万の重要な要素の集合を削除、ビューのポイントをテストすることによって、それが1000ミリ秒程度かかりました。
次のテスト、100万のハッシュキーフィールドを削除し、1360msを取った。この要求DEL期間を扱う、他の要求を完全にブロックされています。
删除一个100万字段的hash键
127.0.0.1:6379> HLEN hlazykey
(integer) 1000000
127.0.0.1:6379> del hlazykey
(integer) 1 (1.36s) 127.0.0.1:6379> SLOWLOG get 1) 1) (integer) 0 2) (integer) 1501314385 3) (integer) 1360908 4) 1) "del" 2) "hlazykey" 5) "127.0.0.1:35595" 6) “"
テスト推定、参照があってもよく、およびハードウェア環境、Redisのバージョンと負荷率
キーの種類 | 商品番号 | 時間のかかります |
---|---|---|
ハッシュ | 〜100万 | 〜1000msで |
リスト | 〜100万 | 〜1000msで |
セットする | 〜100万 | 〜1000msで |
ソートセット | 〜100万 | 〜1000msで |
redis4.0前に、無怠惰なフリー機能、DBAだけ大きなキーをスキャンする同様のトリッキーな方法を通じて、すべての100個の要素を削除します。しかし、「受動的」シナリオの顔に削除されたトリッキーな何もできないキーを、削除。
例えば:私たちは、受動的、Redisの結果としては、20秒以上のブロックされたときのRedisクラスター、ゆっくりとキーの有効期限が切れたTTLで2,000万人以上のハッシュキーフィールド書かれたビジネスは、Redisのは、それをきれいにするために始めた、現在の大規模なクラスタを生成しますフラグメンテーションより20秒によるマスターノードは、要求を処理できず、マスタ・データベース・フェイルオーバーが発生します。
redis4.0した後、あなたが大きな鍵を削除すると、このようなアクティブまたはパッシブとして怠惰な無料の機能を、している、とO(1)時間のかかる命令、サブミリ秒のリターン;バイオバックグラウンドタスクを参照し、実際のリリースRedisの要素がアクションを実行します実行。
怠惰な自由を使用してください
2つのカテゴリに分類され怠け者無料でご利用:最初のカテゴリが自動的にDELコマンドに対応する削除され、第二は、削除する期限切れのキー、削除解消maxmemoryキー追放です。
無料怠惰に使用するキーイニシアチブを削除します。
UNLINKコマンド
UNLINKコマンドは、怠惰なフリーな実装のDELキー機能を削除すると同じです。
コレクションクラスを削除する場合だけでなく、同じ、キーのリンクを解除し、要素の数は64に設定キー場合よりも大きくなる(詳細は後述)、操作個々のバイオに、操作実メモリを解放します。
例としては、次のとおりです:使用UNLINK 2万個の要素を含む大規模なキーマイリストを削除するコマンドが、唯一の0.03ミリ秒で
127.0.0.1:7000> LLEN mylist
(integer) 2000000
127.0.0.1:7000> UNLINK mylist
(integer) 1 127.0.0.1:7000> SLOWLOG get 1) 1) (integer) 1 2) (integer) 1505465188 3) (integer) 30 4) 1) "UNLINK" 2) "mylist" 5) "127.0.0.1:17015" 6) ""
注意:DELコマンドは、ブロックまたは同時の削除
FLUSHALL / FLUSHDB ASYNC
FLUSHALL / FLUSHDBあなたはASYNC非同期のクリーンアップのオプション、インスタンス全体またはDBをクリーンアップでのRedisを追加すると、操作は非同期です。
127.0.0.1:7000> DBSIZE
(integer) 1812295
127.0.0.1:7000> flushall //同步清理实例数据,180万个key耗时1020毫秒
OK
(1.02s)
127.0.0.1:7000> DBSIZE
(integer) 1812637
127.0.0.1:7000> flushall async //异步清理实例数据,180万个key耗时约9毫秒
OK
127.0.0.1:7000> SLOWLOG get
1) 1) (integer) 2996109
2) (integer) 1505465989
3) (integer) 9274 //指令运行耗时9.2毫秒
4) 1) "flushall"
2) "async"
5) "127.0.0.1:20110"
6) ""
無料の怠惰な受動的に使用するキーを削除します。
適用怠惰無料パッシブ削除、シーンの4種類、設定パラメータに対応する各シーンがありますが、デフォルトではオフになっています。
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no slave-lazy-flush no
怠惰な空きメモリの回収効率は依然として比較的高い参照するには、テストからは、実際の状況と本番環境で、オープンパッシブは削除注:
メモリ使用量Redisの怠惰な無料の観測を。
lazyfree-レイジー立ち退き
Redisのメモリ使用量がmaxmeory達するために、そして時にポリシー設定のうち、時にキーのうち、受動的、怠惰な無料のメカニズムを採用するかどうか、
このシーンは、無料の怠惰になっているため、キーメモリのうちの可能な使用はRedisのメモリ乱開発で、その結果、タイムリーにリリースされていない、オーバー制限がmaxmemory。運用テストと組み合わせると、このシナリオでの使用、。
この操作の--todo検証は、ライブラリまたはUNLINKからDELに同期さlazyfree-レイジー期限切れになります。
それはRedisのクリーンアップ怠惰な無料のメカニズムを削除した際に採用するかどうか、その有効期限に達した後、TTLを設定するためのキーがあります。
このシナリオでは、適応的に調整されるため、高速TTL自体の、ターンすることをお勧めします。
lazyfree-レイジーサーバデル
キーが既に存在して取り扱う場合は、いくつかの手順については、それは暗黙的にDELキーで動作します。以下のようrenameコマンドターゲット・キーがすでに存在する場合、Redisのは、これらの目標は、キーの大きなキーであれば、それはブロックするパフォーマンスの問題の導入を削除させていただきます、ターゲット・キーを削除します。このパラメータの設定は、このような問題を解決するものであり、有効にすることをお勧めします。
スレーブレイジーフラッシュ
スレーブマスターは自分のデータをクリーンアップするflushallシーンを実行して、RDBファイルをロードする前に、データの同期スレーブの全額に対して行う、
パラメータの設定は、異常なフラッシュメカニズムを採用するかどうかを決定します。メモリが少し変更された場合、有効にすることをお勧めします。完全同期は、出力バッファが原因急騰するので、これによりメインライブラリのメモリ使用量の増加を低減する、時間のかかる量を低減することができます。
怠け者無料モニター
怠惰な自由インジケータがデータを監視することができ、一つの値のみ:lazyfree_pending_objectsは、Redisのは怠惰なフリー操作、コンテンツを再利用されるのを待っているキーの実際の数を実行表します。これは、単一のキーの多数の要素を反映してか、回復怠惰な空きメモリサイズを待ちません。
この値はある基準値、効率を監視してもよいし、積層Redisの遅延遊離結合の数であり、そのような少量flushall非同期シーンで堆積されます。
怠惰な自由を達成するための簡単な分析
antirez多くの重要な機能と下部構造の機能を実現する自由遅延は変更されている;このセクションは、怠惰なフリー論理機能を実装について説明し、コードがlazyfree.cにおけるソース及びbio.cに主にあります。
UNLINKコマンド
コマンド入力機能unlinkCommandのリンクを解除()関数は、lazyfree怠惰な呼び出しとして識別するかどうか、キー操作を削除()と同じとデルdelGenericCommandを呼び出します。lazyfree場合は、dbAsyncDelete()関数と呼ばれます。
しかし、必ずしもすべてのリンク解除コマンドは怠惰な自由有効、RedisのKEYが最初のコストがLAZYFREE_THRESHOLD怠け者無料。以上であるときにのみ行われ、リリース(コスト)のコストを決定
リリースコスト計算機能キーlazyfreeGetFreeEffort()、セットキーの種類、および満たす対応するコーディング、コストのメタデータキーの数が設定され、それ以外のコストは1です。
例えば:
1リストキー100個の要素が含まれている、そのコストは100無料である
2文字キー512メガバイト、その費用は無料です
見ることができますうち、主な時間を関連するRedisのコスト計算の複雑さの怠惰無料。
lazyfreeGetFreeEffort()ファンクションコード
size_t lazyfreeGetFreeEffort(robj *obj) { if (obj->type == OBJ_LIST) { quicklist *ql = obj->ptr; return ql->len; } else if (obj->type == OBJ_SET && obj->encoding == OBJ_ENCODING_HT) { dict *ht = obj->ptr; return dictSize(ht); } else if (obj->type == OBJ_ZSET && obj->encoding == OBJ_ENCODING_SKIPLIST){ zset *zs = obj->ptr; return zs->zsl->length; } else if (obj->type == OBJ_HASH && obj->encoding == OBJ_ENCODING_HT) { dict *ht = obj->ptr; return dictSize(ht); } else { return 1; /* Everything else is a single allocation. */ } }
dbAsyncDelete()関数のコード部分
#define LAZYFREE_THRESHOLD 64 //根据FREE一个key的cost是否大于64,用于判断是否进行lazy free调用
int dbAsyncDelete(redisDb *db, robj *key) { /* Deleting an entry from the expires dict will not free the sds of * the key, because it is shared with the main dictionary. */ if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr); //从expires中直接删除key dictEntry *de = dictUnlink(db->dict,key->ptr); //进行unlink处理,但不进行实际free操作 if (de) { robj *val = dictGetVal(de); size_t free_effort = lazyfreeGetFreeEffort(val); //评估free当前key的代价 /* If releasing the object is too much work, let's put it into the * lazy free list. */ if (free_effort > LAZYFREE_THRESHOLD) { //如果free当前key cost>64, 则把它放在lazy free的list, 使用bio子线程进行实际free操作,不通过主线程运行 atomicIncr(lazyfree_objects,1); //待处理的lazyfree对象个数加1,通过info命令可查看 bioCreateBackgroundJob(BIO_LAZY_FREE,val,NULL,NULL); dictSetVal(db->dict,de,NULL); } } }
キーを解放するためにバイオ()関数でlazyfreeFreeObjectFromBioThreadを実際の呼び出し
void lazyfreeFreeObjectFromBioThread(robj *o) {
decrRefCount(o); //更新对应引用,根据不同类型,调用不同的free函数
atomicDecr(lazyfree_objects,1); //完成key的free,更新待处理lazyfree的键个数
}
flushall / flushdb非同期命令
flushall / flushdbベルト非同期は、機能emptyDb()emptyDbAsync()を呼び出すとき論理処理遅延遊離又は全体インスタンスDBを実行します。
次のようにemptyDbAsync処理ロジックは次のとおりです。
/* Empty a Redis DB asynchronously. What the function does actually is to
* create a new empty set of hash tables and scheduling the old ones for
* lazy freeing. */
void emptyDbAsync(redisDb *db) { dict *oldht1 = db->dict, *oldht2 = db->expires; //把db的两个hash tables暂存起来 db->dict = dictCreate(&dbDictType,NULL); //为db创建两个空的hash tables db->expires = dictCreate(&keyptrDictType,NULL); atomicIncr(lazyfree_objects,dictSize(oldht1)); //更新待处理lazyfree的键个数,加上db的key个数 bioCreateBackgroundJob(BIO_LAZY_FREE,NULL,oldht1,oldht2);//加入到bio list }
バイオ実際の関数呼び出しlazyfreeFreeDatabaseFromBioThreadリリースDBに
void lazyfreeFreeDatabaseFromBioThread(dict *ht1, dict *ht2) {
size_t numkeys = dictSize(ht1);
dictRelease(ht1);
dictRelease(ht2);
atomicDecr(lazyfree_objects,numkeys);//完成整个DB的free,更新待处理lazyfree的键个数
}
無料の怠惰な受動的に使用するキーを削除します。
4受動的なシーンを削除し、パラメータが上にある場合と呼ばれ、対応するパラメータがオンになっている各シーンのRedisは、決定され、実装上の処理ロジックに対応する怠惰なフリー機能と呼ばれています。
概要
Redisのは、単一のメインスレッドでantirezは常に「レイジーRedisのが良いRedisのである」と強調。そのため
、メインのRedisの本質は、いくつかの怠惰な費用の自由にある(の主にイン・タイム・コピー、メインスレッドのCPU時間のスライスを占める)高の削除スレッドを剥奪ので、大幅に時間を遮断するメインラインを減らし、バイオ子を処理するためのスレッド。これにより、パフォーマンスと安定性の問題で削除結果を減少させます。