Redisデータベース通知機能の実装


詳細
Reidsデータベース通知機能は、クライアントが所定のチャネルまたはモードを購読することによって、データベース内のキーの変化、およびデータベース内のコマンドの実行状況を知ることができる.
たとえば、次のコードは、クライアントが0番データベースでmessageキーに対して実行されるすべてのコマンドを取得する方法を示します.

redis> SUBSCRIBE __keyspace@0__:message
Reading messages... (press Ctrl-C to quit)

1) "subscribe"                  //     
2) "__keyspace@0__:message"
3) (integer) 1

1) "message"                    //    SET   
2) "__keyspace@0__:message"
3) "set"

1) "message"                    //    EXPIRE   
2) "__keyspace@0__:message"
3) "expire"

返信された通知によると,SETとEXPIREの2つのコマンドが前後してキーメッセージを操作していることがわかる.
このような「あるキーがどのコマンドを実行したか」に注目する通知をキー空間通知(key-space notification)と呼び、また、「あるコマンドがどのキーによって実行されたか」に注目するキーイベント通知(key-event notification)と呼ぶ.以下のコードは、クライアントが0番データベース内のDELコマンドを実行したすべてのキーのキーイベント通知を取得する方法の例です.

redis> SUBSCRIBE __keyevent@0__:del
Reading messages... (press Ctrl-C to quit)

1) "subscribe"                 //     
2) "__keyevent@0__:del"
3) (integer) 1

1) "message"                   //   key     DEL   
2) "__keyevent@0__:del"
3) "key"

1) "message"                   //   number     DEL   
2) "__keyevent@0__:del"
3) "number"

サーバのnotify-keyspace-events構成オプションの値は、サーバが送信する通知のタイプを決定します(詳細はRedisの公式ドキュメントの説明を参照してください):
(1)値AKEは,サーバにすべてのタイプのキー空間通知とキーイベント通知を送信させたいことを示す.
(2)値AKは,すべてのタイプのキー空間通知をサーバに送信させたいことを示す.
(3)値AEは,すべてのタイプのキーイベント通知をサーバに送信させたいことを示す.
(4)値KSは,サーバに文字列キーに関するキー空間通知のみを送信させたいことを示す.
(5)値ELは,リストキーに関するキーイベント通知のみをサーバに送信させたいことを示す.
データベース通知を送信する機能はnotifyKeyspaceEvent関数によって実現され,その擬似コードは以下のように実現される.

def notifyKeyspaceEvent(type, event, key, dbid):
    #                      ,     
    if not (server.notify_keyspace_events & type):
        return
    #        
    if server.notify_keyspace_events & REDIS_NOTIFY_KEYSPACE:
        #         “__keyspace@__:”
        #            
        #       
        chan = "__keyspace@{dbid}__:{key}".format(dbid=dbid, key=key)
        #     
        pubsubPublishMessage(chan, event)

    #        
    if server.notify_keyspace_events & REDIS_NOTIFY_KEYEVENT:
        #         “__keyevent@__:”
        #           
        #       
        chan = "__keyevent@{dbid}__:{event}".format(dbid=dbid, event=event)
        #     
        pubsubPublishMessage(chan, key)

その中のpubsubPublishMessage関数はPUBLISHコマンドの実装関数であり、サブスクリプションデータベースから通知されたクライアントが受け取った情報はこの関数から発行され、その具体的な実装の詳細は後述する.
参考書:『Redis設計と実現』第9章-データベース.