Redis 客戶端 Jedis、lettuce 和 Redisson 對比

程式設計師自由之路發表於2020-10-14

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 命令的支援,其官方網址是:http://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 的官網地址是:https://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的官方網址是:https://redisson.org/

優點:

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

缺點:

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

4. 使用建議

結論:lettuce + Redisson

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

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

參考

相關文章