Redis 客戶端 Jedis、lettuce 和 Redisson 對比

Redis 支援多種語言的客戶端,下面列舉了部分 Redis 支援的客戶端語言,大家可以通過官網查看 Redis 支援的客戶端詳情。

  • C語言
  • C++
  • C#
  • Java
  • Python
  • Node.js
  • PHP

Redis 是用單執行緒來處理多個客戶端的訪問,因此作為 Redis 的開發和運維人員需要了解 Redis 服務端和客戶端的通訊協議,以及主流程式語言的 Redis 客戶端使用方法,同時還需要了解客戶端管理的相應 API 以及開發運維中可能遇到的問題。

Redis 客戶端通訊協議

Redis制定了RESP(Redis Serialization Protocol,Redis序列化協議)實現客戶端與服務端的正常交互,這種協議簡單高效,既能夠被機器解析,又容易被人類識別。

RESP可以序列化不同的數據類型,如整型、字元串、數組還有一種特殊的Error類型。需要執行的Redis命令會封裝為類似於字元串數組的請求然後通過Redis客戶端發送到Redis服務端。Redis服務端會基於特定的命令類型選擇對應的一種數據類型進行回復。

1. RESP 發送命令格式

RESP中,發送的數據類型取決於數據報的第一個位元組:

  • 單行字元串的第一個位元組為+
  • 錯誤消息的第一個位元組為-
  • 整型數字的第一個位元組為:
  • 定長字元串的第一個位元組為$
  • RESP數組的第一個位元組為*
數據類型 本文翻譯名稱 基本特徵 例子
Simple String 單行字元串 第一個位元組是+,最後兩個位元組是\r\n,其他位元組是字元串內容 +OK\r\n
Error 錯誤消息 第一個位元組是-,最後兩個位元組是\r\n,其他位元組是異常消息的文本內容 -ERR\r\n
Integer 整型數字 第一個位元組是:,最後兩個位元組是\r\n,其他位元組是數字的文本內容 :100\r\n
Bulk String 定長字元串 第一個位元組是$,緊接著的位元組是內容字元串長度\r\n,最後兩個位元組是\r\n,其他位元組是字元串內容 $4\r\ndoge\r\n
Array RESP數組 第一個位元組是*,緊接著的位元組是元素個數\r\n,最後兩個位元組是\r\n,其他位元組是各個元素的內容,每個元素可以是任意一種數據類型 *2\r\n:100\r\n$4\r\ndoge\r\n

發送的命令格式如下,CRLF代表”\r\n”:

*<參數數量> CRLF
$<參數1的位元組數量> CRLF
<參數1> CRLF
...
$<參數N的位元組數量> CRLF
<參數N> CRLF

set hello world這個命令為例,發送的內容就是這樣的:

*3
$3
SET
$5
hello
$5
world

第一行*3表示有3個參數,$3表示接下來的一個參數有3個位元組,接下來是參數,$5表示下一個參數有5個位元組,接下來是參數,$5表示下一個參數有5個位元組,接下來是參數。

所以set hello world最終發送給redis伺服器的命令是:

*3\r\n$3\r\nSET\r\n$5\r\nhello\r\n$5\r\nworld\r\n

2. RESP 響應內容

Redis的返回結果類型分為以下五種:
        正確回復:在RESP中第一個位元組為"+"
        錯誤回復:在RESP中第一個位元組為"-"
        整數回復:在RESP中第一個位元組為":"
        字元串回復:在RESP中第一個位元組為"$"
        多條字元串回復:在RESP中第一個位元組為"*"

(+) 表示一個正確的狀態資訊,具體資訊是當前行+後面的字元。
(-)  表示一個錯誤資訊,具體資訊是當前行-後面的字元。
(*) 表示消息體總共有多少行,不包括當前行,*後面是具體的行數。
($) 表示下一行數據長度,不包括換行符長度\r\n,$後面則是對應的長度的數據。
(:) 表示返回一個數值,:後面是相應的數位元組符。

有了這個協議,我們就可以編寫程式來和 Redis 服務端進行通訊。由於 Redis 的流行,已經存在了很多流行的開源客戶端。本文主要選擇 Java 領域 Redis 官方推薦的客戶端進行介紹。

Redis 的 Java 客戶端

Redis 官方推薦的 Java 客戶端有Jedis、lettuce 和 Redisson。

1. Jedis

Jedis 是老牌的 Redis 的 Java 實現客戶端,提供了比較全面的 Redis 命令的支援,其官方網址是://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.html。

優點:

  • 支援全面的 Redis 操作特性(可以理解為API比較全面)。

缺點:

  • 使用阻塞的 I/O,且其方法調用都是同步的,程式流需要等到 sockets 處理完 I/O 才能執行,不支援非同步;
  • Jedis 客戶端實例不是執行緒安全的,所以需要通過連接池來使用 Jedis。

2. lettuce

lettuce ([ˈletɪs]),是一種可擴展的執行緒安全的 Redis 客戶端,支援非同步模式。如果避免阻塞和事務操作,如BLPOP和MULTI/EXEC,多個執行緒就可以共享一個連接。lettuce 底層基於 Netty,支援高級的 Redis 特性,比如哨兵,集群,管道,自動重新連接和Redis數據模型。lettuce 的官網地址是://lettuce.io/

優點:

  • 支援同步非同步通訊模式;
  • Lettuce 的 API 是執行緒安全的,如果不是執行阻塞和事務操作,如BLPOP和MULTI/EXEC,多個執行緒就可以共享一個連接。

3. Redisson

Redisson 是一個在 Redis 的基礎上實現的 Java 駐記憶體數據網格(In-Memory Data Grid)。它不僅提供了一系列的分散式的 Java 常用對象,還提供了許多分散式服務。其中包括( BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson 提供了使用Redis 的最簡單和最便捷的方法。Redisson 的宗旨是促進使用者對Redis的關注分離(Separation of Concern),從而讓使用者能夠將精力更集中地放在處理業務邏輯上。Redisson的官方網址是://redisson.org/

優點:

  • 使用者對 Redis 的關注分離,可以類比 Spring 框架,這些框架搭建了應用程式的基礎框架和功能,提升開發效率,讓開發者有更多的時間來關注業務邏輯;
  • 提供很多分散式相關操作服務,例如,分散式鎖,分散式集合,可通過Redis支援延遲隊列等。

缺點:

  • Redisson 對字元串的操作支援比較差。

4. 使用建議

結論:lettuce + Redisson

Jedis 和 lettuce 是比較純粹的 Redis 客戶端,幾乎沒提供什麼高級功能。Jedis 的性能比較差,所以如果你不需要使用 Redis 的高級功能的話,優先推薦使用 lettuce。

Redisson 的優勢是提供了很多開箱即用的 Redis 高級功能,如果你的應用中需要使用到 Redis 的高級功能,建議使用 Redisson。具體 Redisson 的高級功能可以參考://redisson.org/

參考