阿里面試官:Redis不僅僅是做緩存的,你回去再看看吧

你需要一個經典數據庫嗎?

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

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

但隨着事情的發展,現在我們有來高可用的分佈式內存緩存,可以被不同的實例同時使用。

緩存——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作爲主要的持久層。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章