Redis(一):基礎知識以及IO多路複用模型

一:Redis簡介

 

簡單來說 redis 就是一個數據庫,不過與傳統數據庫不同的是 redis 的數據是存在內存中的,所以讀寫速度非常快,因此 redis 被廣泛應用於緩存方向。另外,redis 也經常用來做分佈式鎖。redis 提供了多種數據類型來支持不同的業務場景。除此之外,redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集羣方案。(Redis的業務方向也是面試方向)

 

Redis的優點?

  • 異常快 

Redis 非常快,每秒可執行大約 110000 次的設置(SET)操作,每秒大約可執行 81000 次的讀取/獲取(GET)操作。

  • 支持豐富的數據類型 

Redis 支持開發人員常用的大多數數據類型,例如列表(list),集合(set),排序集(Sort set)和散列(hash)等等。這使得 Redis 很容易被用來解決各種問題,因爲我們知道哪些問題可以更好使用地哪些數據類型來處理解決。

  • 操作具有原子性 

所有 Redis 操作都是原子操作,這確保如果兩個客戶端併發訪問,Redis 服務器能接收更新的值。

  • 多實用工具 

Redis 是一個多實用工具,可用於多種用例,如:緩存,消息隊列(Redis 本地支持發佈/訂閱),應用程序中的任何短期數據,例如,web應用程序中的會話,網頁命中計數等

 

Redis緩存的意義在於?

“高性能”和“高併發”兩個方面

高性能:

假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢,因爲是從硬盤上讀取的。將該用戶訪問的數據存在緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。如果數據庫中的對應數據改變的之後,同步改變緩存中相應的數據即可!

 

高併發:

直接操作緩存能夠承受的請求是遠遠大於直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這裏而不用經過數據庫。

 

爲什麼要用 redis 而不用 map/guava 做緩存?

緩存分爲本地緩存和分佈式緩存。以 Java 爲例,使用自帶的 map 或者 guava 實現的是本地緩存,最主要的特點是輕量以及快速,生命週期隨着 jvm 的銷燬而結束,並且在多實例的情況下,每個實例都需要各自保存一份緩存,緩存不具有一致性。

使用 redis 或 memcached 之類的稱爲分佈式緩存,在多實例的情況下,各實例共用一份緩存數據,緩存具有一致性。缺點是需要保持 redis 或 memcached服務的高可用,整個程序架構上較爲複雜。

 

二:Redis 的線程模型

 

redis 內部使用文件事件處理器 file event handler,這個文件事件處理器是單線程的,所以 redis 才叫做單線程的模型。它採用 IO 多路複用機制同時監聽多個 socket,根據 socket 上的事件來選擇對應的事件處理器進行處理。

文件事件處理器的結構包含 4 個部分:

  • 多個 socket
  • IO 多路複用程序
  • 文件事件分派器
  • 事件處理器(連接應答處理器、命令請求處理器、命令回覆處理器)

多個 socket 可能會併發產生不同的操作,每個操作對應不同的文件事件,但是 IO 多路複用程序會監聽多個 socket,會將 socket 產生的事件放入隊列中排隊,事件分派器每次從隊列中取出一個事件,把該事件交給對應的事件處理器進行處理。

 

redis 和 memcached 的區別

 

對於 redis 和 memcached 我總結了下面四點。現在公司一般都是用 redis 來實現緩存,而且 redis 自身也越來越強大了!

  1. redis支持更豐富的數據類型(支持更復雜的應用場景)

Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。memcache支持簡單的數據類型String。

  1. Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啓的時候可以再次加載進行使用,而Memecache把數據全部存在內存之中。
  2. 集羣模式:memcached沒有原生的集羣模式,需要依靠客戶端來實現往集羣中分片寫入數據;但是 redis 目前是原生支持 cluster 模式的.
  3. Memcached是多線程,非阻塞IO複用的網絡模型;Redis使用單線程的多路 IO 複用模型。

 

IO多路複用模型簡圖如下:

 

重點:

要明白,通信是通過 socket 來完成的,不懂的同學可以先去看一看 socket 網絡編程

首先,redis 服務端進程初始化的時候,會將 server socket 的 AE_READABLE 事件與連接應答處理器關聯。

客戶端 socket01 向 redis 進程的 server socket 請求建立連接,此時 server socket 會產生一個 AE_READABLE 事件,IO 多路複用程序監聽到 server socket 產生的事件後,將該 socket 壓入隊列中。文件事件分派器從隊列中獲取 socket,交給連接應答處理器。連接應答處理器會創建一個能與客戶端通信的 socket01,並將該 socket01 的 AE_READABLE 事件與命令請求處理器關聯。

 

假設此時客戶端發送了一個 set key value 請求,此時 redis 中的 socket01 會生 AE_READABLE 事件,IO 多路複用程序將 socket01 壓入隊列,此時事件分派器從隊列中獲取到 socket01 產生的 AE_READABLE 事件,由於前面 socket01 的 AE_READABLE 事件已經與命令請求處理器關聯,因此事件分派器將事件交給命令請求處理器來處理。命令請求處理器讀取 socket01 的 key value 並在自己內存中完成 key value 的設置。操作完成後,它會將 socket01 的 AE_WRITABLE 事件與命令回覆處理器關聯。

 

如果此時客戶端準備好接收返回結果了,那麼 redis 中的 socket01 會產生一個 AE_WRITABLE 事件,同樣壓入隊列中,事件分派器找到相關聯的命令回覆處理器,由命令回覆處理器對 socket01 輸入本次操作的一個結果,比如 ok,之後解除 socket01 的 AE_WRITABLE 事件命令回覆處理器的關聯。

 

爲啥 redis 單線程模型也能效率這麼高?

 

  • 純內存操作。
  • 核心是基於非阻塞的 IO 多路複用機制。
  • C 語言實現,一般來說,C 語言實現的程序“距離”操作系統更近,執行速度相對會更快。
  • 單線程反而避免了多線程的頻繁上下文切換問題,預防了多線程可能產生的競爭問題。

 

redis 事務

Redis 通過 MULTI、EXEC、WATCH 等命令來實現事務(transaction)功能。事務提供了一種將多個命令請求打包,然後一次性、按順序地執行多個命令的機制,並且在事務執行期間,服務器不會中斷事務而改去執行其他客戶端的命令請求,它會將事務中的所有命令都執行完畢,然後纔去處理其他客戶端的命令請求。

在傳統的關係式數據庫中,常常用 ACID 性質來檢驗事務功能的可靠性和安全性。在 Redis 中,事務總是具有原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation),並且當 Redis 運行在某種特定的持久化模式下時,事務也具有持久性(Durability)。

你們的老婆來了!

 

 

 

 

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