Redis不僅僅是快取,還是……

碼農譯站發表於2020-12-26

你需要一個經典資料庫嗎?

一段時間以來,巨大數量的資料處理迫使所有的應用程式在資料庫層前新增快取策略。即使經典資料庫進行了大量的下劃線優化,仍然不能提供足夠的速度和可用性。主要原因在於資料儲存越遠,獲取資料就越困難。另一個原因是因為資料庫中的資料通常儲存在磁碟中,而不是在記憶體。經典資料庫卻是在記憶體上嵌入了快取來優化,但是擁有一個專用的獨立快取也是一種很常用的策略。

在解決訪問資料庫的效能問題,通常的解決方案是快取。快取並不新鮮,快取實際上是把經常訪問的少量資料儲存在離你更近的地方。我們在處理器上有快取,資料庫中也有快取,你甚至可以在自己的應用中編寫快取。

但隨著事情的發展,現在我們有來高可用的分散式記憶體快取,可以被不同的例項同時使用。

快取——Redis

也許最流行的分散式記憶體資料儲存是Redis,它不是快取,但被當作快取使用。 引用官方的描述如下:

Redis是一個開源的(BSD協議),記憶體中的資料結構儲存,它可以用作資料庫,快取,訊息代理。它支援的資料結構包括字串,雜湊,列表,集合,有序集合,點陣圖,超級日誌,具有半徑查詢和流的地理空間索引和流,Redis具有內建複製,Lua指令碼,LRU驅逐,事務和不同級別的磁碟持久化,並通過Redis哨兵和Redis叢集自動分割槽。

Redis速度很快,它被認為是目前最快的資料儲存之一。它對CPU快取進行了優化,並且沒有上下文切換。從一開始它就被設計成了記憶體資料庫,這不僅意味著將資料從磁碟移動到記憶體,它從一開始就針對性的優化了。

由於Redis速度非常快,可以儲存各種資料結構,因此它是分散式快取的一個很好的備選。

因為作為快取,Redis獲得了非常高的人氣。有一些快取載入器庫在使用Redis作為應用程式和資料庫之間的快取層。以Redisson地圖載入器為例:

因此,使用分散式快取可以極大的提高效能。但是程式碼和架構變得更復雜了。資料被複制到資料庫和快取中,我們必須保持它們的資料同步。程式碼應該管理整個快取策略,控制快取失效,重新填充快取,都是為了保持資料的一致性。我們實現了更高的效能和可伸縮性,但引入了高風險的複雜性。

資料是重複的

你可能會問為什麼要在兩個地方都儲存資料?不能只儲存Redis中的資料嗎?如果這樣做我們可以減少程式碼的複雜性。但首先讓我們看看經典資料庫的一下特點和優勢,看看我們是否可以直接使用Redis實現這些。

關係型資料庫的優點 

傳統來說,快取是不會長期儲存資料的。我們將資料儲存在快取中只是為了快速的訪問,但是為了長時間的永續性,我們通常使用一箇中央資料庫。

除了資料的永續性以外,關係型資料庫提供了資料一致性等其他特點。使用關係型資料庫,你可以定義資料間的關係,約束,複雜查詢,構建它是為了保證多個相關表間的一致性。

它有一些重要的優勢,即使NoSQL資料庫很流行,關係型資料庫也不會很快消失。

但是使用Redis作為快取和關係型資料庫搭配使用,增加了一層複雜性,因為你必須通過程式碼保持兩者的資料同步。

考慮到你的快取策略,你不得不構建一些複雜的程式碼在Redis和資料庫間進行資料傳送。不要誤解我的意思,有時候你必須這麼做。就像之前提到的,關係型資料庫有它的優點,我們不能把它扔掉。

但是我們必須每次都這麼做嗎?如果不同資料間不需要非常複雜的關係,而只儲存一個鍵對映就足夠了呢?我們是不是可以不用關係型資料庫了?

 Redis作為中央資料儲存

 如前所述,關係型資料庫的優點是一致性和永續性。如果我們不需要資料之間的關係對映,那麼它將只保留永續性。有很多NoSQL資料庫提供鍵對映儲存,但我們可以直接使用Redis。

Redis持久化

Redis有兩種持久化模型:RDB和AOF。

RDB在指定的時間間隔儲存資料快照。它們非常適合快速恢復備份。RDB最大化了Redis的效能,因為父程式所做的唯一工作就是fork建立快照的子程式。

但是由於RDB在一定時間間隔執行計劃,如果你無法承受丟失一些資料,那麼這就不是一個好的選擇。fork是一個高成本的操作,不能在每次資料變化都進行fork,因此可能會出現最近的資料沒有被儲存在快照中的情況。

AOF是一個不同的持久化模型。它是由一個只能追加的檔案組成,只在其中新增所有資料。它更持久,因為fsync策略通常比整個RDB更有計劃性。由於該檔案僅用於追加,因此資料是不可更改的。即使在最後一條資料沒有完全寫完而出現斷電,也可以很容易的重新斷電前的構建狀態。

但是它也有缺點。第一個是AOF檔案通常比RDB更大。另外,如果fsync策略被排程的太頻繁,舉個例子,在每次寫命令之後,那麼效能會大打折扣。在預設情況下,fsync每秒執行一次。

你應該使用哪個?

如果你想要一個類似Postgres提供的安全級別,你將不得不兩種情況都使用。使用RDB可以讓你在重啟後更快的恢復備份;使用AOF可以避免資料丟失。但是如果你能承受一些資料損失,那可以只使用RDB。記住,Redis會把它們合併成一個單一的持久化模型。

其他優勢

 未來是屬於位元組定址的

由於磁碟旋轉在很長一段時間都是持久化單元,所以當前的大多數資料庫仍然在適應磁碟的旋轉方面進行優化。比如資料定位,以減少磁碟旋轉滯後,甚至選擇了專門的格式,將索引放在了碟片的特定部分。但是這些優化對於當前的技術,比如SSD,是沒有意義的。Redis儲存資料是為位元組定址優化的。未來是屬於位元組定址的,而Redis已經在那裡了。

可伸縮性和高可用性

Redis提供了不同的方式來實現伸縮性和高可用性。

你可以在不同的Redis節點上分割資料來實現水平的可擴充套件性。分片將減輕單個例項的負擔,你將受益於多核和計算能力。但是你應該知道分片的侷限性,因為不能支援多鍵操作和事務。

通過複製獲得高可用性。主節點是同步複製的,可以免受節點故障,資料中心故障和Redis程式故障。如果主節點當機,副節點將會取而代之。在不同的AZ中也有一個副本,這將保護你免受災難時間的影響,比如整個AZ失敗。

如果你打算使用Redis企業叢集,所有的這些對你都是抽象的,你將擁有分片和高可用性,而不需要額外的程式碼。你可以通過編碼連線到一個Redis例項。

複雜資料結構

Redis不僅可以處理字串,還可以處理不同的資料結構,如:二進位制安全字串,列表,集合,排序集合,點陣圖,超級日誌,流等等。這使得Redis不僅是一個鍵值儲存,更是一個完整的資料結構伺服器。

不是銀彈

一切聽起來都非常棒,但是作為一個事實,沒什麼東西是銀彈,Redis也不是。主要的缺點是所有的資料都應該裝進記憶體中。這使Redis適合那些有足夠記憶體進行儲存的資料。如果沒有,那就必須將資料拆分。但是你會失去一下保證,如事務,管道,或釋出/訂閱。

結論

在很長一段時間裡,Redis被認為只是一個快取。一個非常好的分散式快取,但仍然只是一個應用程式和主資料庫之間的快取。正如你所看到的,Redis不僅僅是一個快取,它試圖擺脫這個誤解。Redis不是一個快取,它是一個分散式資料儲存。它可以以執行緒安全模式以令人難以置信的速度處理不同的資料結構,併為資料永續性提供了不同的機制。

考慮到所有這些,即使Redis被非常成功地用作快取,它還是可以做更多的事情。如果你不需要一些像關係資料和高儲存的SQL屬性,為什麼你要在應用程式中建立一個複雜的三層系統?Redis作為快取和還是資料庫?在這些情況下,你可以只使用Redis作為主要的持久層。

歡迎關注我的公眾號,如果你有喜歡的外文技術文章,可以通過公眾號留言推薦給我。

原文連結:https://dzone.com/articles/redis-is-not-just-a-cache

相關文章