redis--listブロックの詳細
redisではblpopがチェーンテーブルのブロック操作を実現し,クライアント接続がlistにデータがない場合にブロックされる.これは、redis自体が単一スレッドサービスであり、ブロッククライアントがサーバへのリンクを維持している場合、他のコマンドの実行をブロックするのではないかという疑問を抱かせた.
答えは明らかにできない.これはredisブロック命令の実現原理にかかわる.RedisサーバにはIOループとタイミングイベントの2つのループがあることを知っています.IOサイクルでは、redisがクライアント接続応答、コマンドリクエスト処理、コマンド処理結果返信などを完了し、タイミングサイクルではredisが期限切れkeyの検出などを完了する.redis一次接続処理のプロセスは、IO多重検出ソケット状態、ソケットイベント割り当て、リクエストイベント処理のいくつかの重要なステップを含む.
redisはblpopコマンド処理プロセスの場合、まずkeyに対応するlistを検索し、存在する場合、popはクライアントにデータ応答する.そうでなければ対応するkey pushをblocking_keysデータ構造では,対応するvalueはブロックされたclientである.次のpushコマンドが発行されると、サーバはblocking_をチェックします.keysに対応するkeyが存在するかどうか、存在する場合はready_にkeyを追加keysチェーンテーブルにvalueを挿入し、クライアントに応答します.
サービス側は、各イベントサイクルでクライアント要求を処理した後、ready_を巡回する.keysチェーンテーブル、blocking_keysチェーンテーブルには対応するclientが見つかり、応答し、プロセス全体がイベントループの実行をブロックしない.だから、総じて言えばredis serverはready_を通じてkeysとblocking_keysの2つのチェーンテーブルとイベントループは、ブロックされたイベントを処理する.
ステップ1:pushコマンドの処理時にkeyをready_に追加keys中
1つのリストの要素がnullの場合、そのキーも存在しないので、1つのキーに要素を追加すると必ず1つのキーが追加され、dbAdd()関数が呼び出されるので、この関数でvalueがリストタイプであると判断した場合、signalListAsReady()関数が実行される
このデータはready_にkeyを追加しますkeysチェーンテーブルの中
第2部:いずれかのクライアントのコマンド要求を処理した後、順次ready_を巡回するkeysチェーンテーブルは、対応するクライアントと対応するkeyを応答します.
readQueryFromClient -> processCommand-> handleClientsBlockedOnLists -> serveClientBlockedOnList
https://www.jianshu.com/p/xsMzfn
答えは明らかにできない.これはredisブロック命令の実現原理にかかわる.RedisサーバにはIOループとタイミングイベントの2つのループがあることを知っています.IOサイクルでは、redisがクライアント接続応答、コマンドリクエスト処理、コマンド処理結果返信などを完了し、タイミングサイクルではredisが期限切れkeyの検出などを完了する.redis一次接続処理のプロセスは、IO多重検出ソケット状態、ソケットイベント割り当て、リクエストイベント処理のいくつかの重要なステップを含む.
redisはblpopコマンド処理プロセスの場合、まずkeyに対応するlistを検索し、存在する場合、popはクライアントにデータ応答する.そうでなければ対応するkey pushをblocking_keysデータ構造では,対応するvalueはブロックされたclientである.次のpushコマンドが発行されると、サーバはblocking_をチェックします.keysに対応するkeyが存在するかどうか、存在する場合はready_にkeyを追加keysチェーンテーブルにvalueを挿入し、クライアントに応答します.
サービス側は、各イベントサイクルでクライアント要求を処理した後、ready_を巡回する.keysチェーンテーブル、blocking_keysチェーンテーブルには対応するclientが見つかり、応答し、プロセス全体がイベントループの実行をブロックしない.だから、総じて言えばredis serverはready_を通じてkeysとblocking_keysの2つのチェーンテーブルとイベントループは、ブロックされたイベントを処理する.
ステップ1:pushコマンドの処理時にkeyをready_に追加keys中
1つのリストの要素がnullの場合、そのキーも存在しないので、1つのキーに要素を追加すると必ず1つのキーが追加され、dbAdd()関数が呼び出されるので、この関数でvalueがリストタイプであると判断した場合、signalListAsReady()関数が実行される
void dbAdd(redisDb *db, robj *key, robj *val) {
sds copy = sdsdup(key->ptr); // key
int retval = dictAdd(db->dict, copy, val); // key-val
serverAssertWithInfo(NULL,key,retval == DICT_OK);
// , , key ready_keys
if (val->type == OBJ_LIST) signalListAsReady(db, key);
// , key
if (server.cluster_enabled) slotToKeyAdd(key);
}
このデータはready_にkeyを追加しますkeysチェーンテーブルの中
// client key push , key ready_keys,key
void signalListAsReady(redisDb *db, robj *key) {
readyList *rl;
/* No clients blocking for this key? No need to queue it. */
// key
if (dictFind(db->blocking_keys,key) == NULL) return;
/* Key was already signaled? No need to queue it again. */
//key ready_keys ,
if (dictFind(db->ready_keys,key) != NULL) return;
/* Ok, we need to queue this key into server.ready_keys. */
// key ready_keys
// readyList , client
rl = zmalloc(sizeof(*rl));
rl->key = key; //
rl->db = db; //
incrRefCount(key);
// rl server.ready_keys
listAddNodeTail(server.ready_keys,rl);
/* We also add the key in the db->ready_keys dictionary in order
* to avoid adding it multiple times into a list with a simple O(1)
* check. */
// key ready_keys ,
incrRefCount(key);
serverAssert(dictAdd(db->ready_keys,key,NULL) == DICT_OK);
}
第2部:いずれかのクライアントのコマンド要求を処理した後、順次ready_を巡回するkeysチェーンテーブルは、対応するクライアントと対応するkeyを応答します.
readQueryFromClient -> processCommand-> handleClientsBlockedOnLists -> serveClientBlockedOnList
https://www.jianshu.com/p/xsMzfn