詳細Redisのリスト閉塞

Redisのリストは、データのない、リスト内のクライアント接続がブロックされます、blpopブロッキング操作で実現することができます。これは私に質問をした、自身をRedisのシングルスレッドのサービスで、クライアントをブロックすると、サーバーとのつながりを維持している場合、それは他のコマンドの実行にそれをブロックしませんか?

明白な答えは、コマンドを遮断する原則のRedisの実現を伴う、ないです。IOサイクルと、時限イベント:我々はRedisのサーバーに2つのループがあることを知っています。IOサイクル、Redisのクライアント接続応答完了、コマンド要求の処理とコマンド処理応答、およびタイミングサイクルの結果では、検出は、Redisのキー等を有効期限が切れて達成されます。いくつかの重要な工程を含む接続処理手順をRedisの:IOマルチプレクサ状態は、ソケット、ソケット・イベントを検出し、要求イベント処理をディスパッチします。

存在する場合、最初のキーがクライアントにデータを飛び出さに応じて、対応するリストを検索しますRedisのコマンド処理手順をblpopとき。それ以外の場合はblocking_keysの間でキープッシュデータ構造に対応し、対応する値は、クライアントにブロックされています。次のプッシュコマンドが発行されると、blocking_keysうち対応するキーサーバチェックがあるかどうか存在する場合、リストready_keysに追加されるキーながらリンクリスト及びクライアントへの応答の値。

クライアント要求は、応答して、ready_keysリストをトラバースし、blocking_keysの中から対応するクライアントのリストを検索する各イベントループの終了時にサービスが終了した後、全体のプロセスは、イベント・ループを遮断する実行しないであろうだから、一般的には、Redisのサーバーはready_keysとblocking_keys二つのリストとイベントループによって封鎖イベントに対処することです。


最初のステップ:ready_keysでプッシュコマンドに追加のキーを扱うには

要素のリストがnullの場合、それは、キーが存在しない要素がキーに追加されたときに、新しいキーでなければならないもの値が決定された場合、関数内ので、dbAdd()関数を呼び出しますリストタイプ、実行さ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_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);
}


パートII:コマンド処理した後、任意のクライアント要求は、クライアントとの応答に対応するキーに対応してリンクリストを、横断、ready_keysあります

readQueryFromClient - > processCommand-> handleClientsBlockedOnLists - > serveClientBlockedOnList


https://www.jianshu.com/p/xsMzfn

おすすめ

転載: blog.csdn.net/asdfsadfasdfsa/article/details/95315048