使用 wireshark 分析 redis 協議

HilTZDK 8年前發布 | 17K 次閱讀 Redis NoSQL數據庫

來自: http://holys.im/2016/01/24/learn-redis-protocol-with-wireshark


如果想要和 redis 打交道, 譬如實現某種語言的 redis 的客戶端, 實現 redis 的 proxy,都得懂 redis 的數據序列化協議 REdis Serialization Protocol(RESP)(MySQL 同理). Redis使用 TCP 作為其數據傳輸協議,而分析 TCP 包就不得不祭出 wireshark 這個神器了。 雖然wireshark 可以分析 TCP 包, 但是直接看 TCP 包不是那么直觀的看出與 redis 的關系的。此時,我們將借助 Redis-wireshark 這個wireshark 插件來分析協議。

備注

  1. 我當前所用的 redis 版本是 2.8。
  2. 本文只是分析 C-S 模型的 redis server 的協議。redis cluster 是另一套二進制協議。

Tips

如果redis-server 和 redis-cli 都是運行在本機, wireshark 應該使用 loopback這個虛擬接口來查看數據。至于原因, wireshark 的文檔是這么解釋的:

If you are trying to capture traffic from a machine to itself, that traffic will not be sent over a real network interface, even if it’s being sent to an address on one of the machine’s network adapters. This means that you will not see it if you are trying to capture on, for example, the interface device for the adapter to which the destination address is assigned. You will only see it if you capture on the “loopback interface”, if there is such an interface and it is possible to capture on it;

https://wiki.wireshark.org/CaptureSetup/Loopback

</blockquote>

wireshark

分析過程

redis 使用第一個字符來區分不同的數據類型

  1. + 表示simple string
  2. - 表示錯誤 error
  3. : 表示冒號表示整數
  4. $ 表示bulk string
  5. * 表示arrays
  6. </ol>

    使用\r\n CRLF 字符來表示結尾

    舉例:

    1、 Simple string

    12
    +OK\r\n+PONG\r\n

    C745546B-D7AD-42E1-863A-43A8141B460B

    2、 error

    1
    -ERR unknown command ‘ada’\r\n

    F145FAE4-FBB8-4E05-869D-42A379B47420

    3、 integer
    刪除一個不存在的key, 返回了下面的內容

    1 
    :0\r\n

    229DCAA5-60D7-4EBD-9842-4E601818D1F4

    4、 bulk srting
    bulk string 用來表示一個二進制安全的字符。
    其編碼結構是:

    1. $ 開頭,后面緊跟字符的字節長度,然后是 \r\n 結尾;
    2. 實際的字符內容;
    3. \r\n 結尾。
    4. </ol>

      foobar 可表示為 $6\r\nfoobar\r\n,空串可表示為 $0\r\n\r\n

      bulk string 好像沒有單獨的用途, 抓包圖片見 arrays。

      5、 arrays
      也叫 multi bulk。
      arrays 的編碼結構:

      1. * 星號開頭, 然后是元素的個數(十進制表示), \r\n 結尾
      2. 多個用 bulk string 表示元素
      3. </ol>

        客戶端發送的內容 都是用 array 表示
        如:發送 ping 命令

        1 
        *1\r\n$4\r\nping\r\n

        2CCA3B72-CD20-4B8F-BA83-E9BF4E925986

        小結

        明白了 redis 的協議之后,我們就可以嘗試編寫一個 redis client 了。下篇我會嘗試去講述如何寫一個簡單的 redis client。其實寫 client 只需要關心如何encode, decode 是服務端需要做的事情。當然 client 還需要關心連接池等問題。敬請期待!

        </span>

 本文由用戶 HilTZDK 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!