聊聊 Spring Data Redis本質
今天花半小時補一篇技術文章純純是因為早上發(fā)的那篇感悟隨記很多人可能會認為不是技術文章。而一般這種文章的閱讀量會遠高于技術文章。為了不破壞公眾號的基調,今天寫篇技術文章明天一早發(fā)出去。大家上班路上看到的是:這還是一個技術公眾號。但是我想說的是上篇文章我是在講技術,如果對技術的理解過于狹隘,那在工作中會很容易進入瓶頸期。
咱們宏觀到微觀來審視一下:業(yè)務的服務在技術上需要解決4個問題:分布式、通信、存儲和服務治理。
圖片
在存儲方面,spring家族在使用時做了封裝就是spring data。spring data本質上是解決與存儲層的通信問題,提供的是與存儲層的通信規(guī)范。Redis是其中一種常用的存儲。
在19年之前,Jedis還是主流的redis客戶端驅動,但是近幾年lettuce占據(jù)了主流的市場。這也是spring data redis的默認支持。原因是當一個Jedis連接要進行多個不同的客戶端數(shù)據(jù)操作的時候有可能產(chǎn)生線程安全的問題,而且lettuce還支持響應式編程的模式。就是說spring data redis本身支持同步和異步兩種編程模式,而lettuce支持同步、異步和響應式三種編程模式。
首先來看lettuce是什么。它是一個驅動?!膀寗印蓖ǔV傅氖且环N軟件組件,它允許操作系統(tǒng)或應用程序與硬件或其他軟件進行交互。在 Java 和其他編程語言中,驅動通常是指用于連接和操作特定類型數(shù)據(jù)庫、消息隊列或緩存等系統(tǒng)的庫或框架。
驅動的四個作用
- 連接管理: 驅動負責建立與 Redis 服務器的連接,并管理連接的生命周期。
- 命令執(zhí)行: 驅動提供了方法來執(zhí)行 Redis 命令并處理返回的結果。
- 錯誤處理: 驅動處理與 Redis 交互時可能出現(xiàn)的錯誤和異常。
- 數(shù)據(jù)類型支持: 驅動通常會封裝 Redis 的數(shù)據(jù)類型(如字符串、哈希、列表等),提供更易用的接口。
所以不管是Jedis還是Lettuce,都會負責連接工廠的創(chuàng)建。
@Bean
public LettuceConnectionFactory connectionFactory() {
RedisStandaloneConfiguration cfg = new RedisStandaloneConfiguration();
cfg.setHostName(host);
cfg.setPort(Integer.parseInt(port));
cfg.setDatabase(database);
cfg.setPassword(password);
return new LettuceConnectionFactory(cfg);
}
實際使用的時候咱們還是使用RedisTemplate
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
// 創(chuàng)建實例對象
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.afterPropertiesSet();
return template;
}
有沒有朋友有這樣的疑惑:RedisTemplate看這個名字應該是使用了模板方法的設計模式,模板方法特征不是應該提供一個抽象類,有不同的實現(xiàn)嗎?怎么看源碼好像也沒用啊。這個問題問得很好,年輕人。
為什么我知道你是個年輕人呢。因為RedisTemplate在早期的版本中的確是一個抽象方法,具體使用的時候還是需要使用它的子類,那時候是一種基于行為模式的模板方法。而現(xiàn)在呢?
仍然是一個模板方法的設計模式,除了可以直接使用的RedisTemplate,我們其實還有StringRedisTemplate這個子類。后來又有了一個ReactiveRedisTemplate,它其實并不是RedisTemplate的子類。
咱們提到Lettuce是支持響應式編程的。
響應式編程是一種編程范式,強調異步數(shù)據(jù)流的處理和對變化的響應。它允許程序以聲明性方式處理數(shù)據(jù)流和變化,通常用于處理用戶界面、事件驅動的系統(tǒng)、流式數(shù)據(jù)等場景。響應式編程的核心思想是將數(shù)據(jù)視為流,并對這些流中的變化作出反應。
它有幾個核心概念:
- 數(shù)據(jù)流:
- 數(shù)據(jù)流是指一系列的數(shù)據(jù)變化或事件。響應式編程中,數(shù)據(jù)流可以是用戶輸入、網(wǎng)絡請求、傳感器數(shù)據(jù)等。
- 觀察者模式:
響應式編程通常基于觀察者模式,即一個對象(被觀察者)維護一系列依賴于它的對象(觀察者),并在其狀態(tài)發(fā)生變化時自動通知這些觀察者。
異步處理:
響應式編程強調非阻塞的異步處理,通過回調函數(shù)、Promises 或者流的方式來處理數(shù)據(jù)變化,而不是等待操作完成。
聲明性編程:
響應式編程允許開發(fā)者以聲明的方式定義數(shù)據(jù)流的處理邏輯,而不是以命令式的方式逐步執(zhí)行。
響應式編程的優(yōu)點
- 簡化異步編程: 通過將異步操作以流的形式處理,減少了回調地獄(callback hell)的問題。
- 提高可讀性: 代碼更簡潔,邏輯清晰,更容易理解和維護。
- 易于組合: 可以方便地將多個數(shù)據(jù)流進行組合和轉換,形成復雜的邏輯。
回調地獄(Callback Hell)是指在使用異步編程時,由于多層嵌套的回調函數(shù)導致代碼變得難以閱讀、理解和維護的現(xiàn)象。它通常發(fā)生在處理多個異步操作時,每個操作都依賴于前一個操作的結果,導致代碼結構像金字塔一樣逐漸加深。
回調地獄的特征
- 深層嵌套: 每個異步操作的結果都需要嵌套在另一個回調中,使得代碼層級過深。
- 可讀性差: 多層嵌套使得代碼難以理解,邏輯不清晰,增加了維護的難度。
- 錯誤處理復雜: 在嵌套的回調中,錯誤處理變得更加復雜,因為每個回調都需要單獨處理錯誤。
Spring Data Redis默認是異步的,而使用響應式編程的公司實際也不多見。因為響應式編程是受到環(huán)境制約的。它要基于WebFlex,而WebFlex與咱們常用的Web是二選一的。