Redis必知必會

1.1 什麼是Redis?

提起Redis, 我們知道

  • Redis 是一個高性能的key-value緩存NoSql數據庫,它完全開源且免費。
  • Redis支持五種數據類型:string(字符串), hash(哈希), list(列表), set(集合), zset(sorted set 有序集合)
  • Redis它的每一個鍵值最大可以存儲512MB 數據且支持消息訂閱和數據持久化。
  • Redis是單線程的,但這裏的單線程僅指Redis負責存取這塊的線程只有一個,而非Redis中只有一個線程

1.2 爲什麼Redis 那麼快?

在學習的過程中不知道你有沒有好奇過,爲什麼Redis 那麼快?

難道僅僅因爲它是內存數據庫?僅僅因爲它是Key,Value 存儲?

我想問題的答案肯定不止是這樣。

那麼到底爲什麼它這麼快呢?

1.2.1 基於內存存取

我們知道在操作系統中如果數據放在不同的地方存取速度是不一樣的,很容易得出這樣一個結論:

CPU寄存器存儲的數據處理速度> 內存存儲的數據處理速度> 磁盤存儲的數據處理速度。

所以基於內存存取確實是它快的一個原因。

1.2.2 I/O 多路複用

Redis 快的第二個原因是因爲它使用了IO多路複用。

在開始講解什麼是IO多路複用之前,先來回顧下Java 中的I/O 相關的知識。

我們知道在Java中,如果想對數據進行讀取和寫入可以按照一個一個字節進行讀取和寫入,也可以按照一個一個字符進行讀取和寫入,但是這兩種讀取和寫入有一個缺點,它是阻塞的。

爲什麼這麼說呢? 我們拿網絡通信I/O 中的Socket 通信爲例

  • 當用戶發出一個Socket 請求,服務端需要開啓一個線程對這個請求進行Accept 接受處理。
  • 然後用戶開始發送數據,在用戶發送字節/字符的過程中,可能出現停頓,比如每隔十分鐘發送一句話。
  • 在上面用戶發送數據的過程中,這個線程啥事也不能幹,只能乾等着,收到數據就處理沒收到就乾等着。

所以說它是阻塞的。

至於NIO, 它是怎麼解決這個問題的呢?

NIO並不是說在 I/O 讀取和寫入的時候加一個Buffer 緩衝區就是NIO.

NIO代表的一個詞彙叫着IO多路複用,它有三個核心概念,Chanel(通道), Buffer(緩衝區), selector。

它用的是事件機制,使用一個線程接受所有的Socket 請求,然後將所有請求都會發送到Channel ,然後註冊到Selector 中,然後Selector 調用其他線程去處理任務。

也就是說三個Client Socket, 無論哪個Socket 發送了消息,selector 都會知道,然後將從Channel 收到的消息交給線程處理,這期間線程不需要阻塞等待單個Socket 的請求輸入。
在這裏插入圖片描述
在多路複用 IO 模型中,會有一個線程不斷去輪詢多個 socket 的狀態,只有當 socket 真正有讀寫事件時,才真 正調用實際的 IO 讀寫操作(Handle Processor Thread)。

因爲在多路複用 IO 模型中,只需要使用一個線程就可以管理多個 socket,系統不需要建立新的進程或者線程,也不必維護這些線程和進程,並且只有在真正有 socket 讀寫事件進行時,纔會使用 IO 資源,所以它大大減少了資源佔用。

在 Java NIO 中,是通 過 selector.select()去查詢每個通道是否有到達事件,如果沒有事件,則一直阻塞在那裏,因此這 種方式會導致用戶線程的阻塞。多路複用 IO 模式,通過一個線程就可以管理多個 socket,只有當 socket 真正有讀寫事件發生纔會佔用資源來進行實際的讀寫操作。因此,多路複用 IO 比較適合連 接數比較多的情況。

所以說 I/O 多路複用是指 多路網絡連接複用一個io線程

更多示例和理解見:

1.3 Redis 是如何保證數據不丟失的?

我們知道Redis 數據大多數情況是存儲在內存中的,然而數據如果只存儲在內存中是很容易丟失的。

爲了解決這個問題,Redis 提供了多種不同級別的持久化方式:

  • 一種是RDB(Redis DataBase) 指定的時間間隔內生成數據集的時間點快照.
  • 另一種是AOF(Append Only File):數據持久化到文件中

注意

  • 開啓AOF持久化,並將appendfsync=always,安全性最高,但是效率比較差。
  • 因爲每次修改數據後,都會將數據刷到aof文件中

1.4 Redis 支持分佈式事務麼?

Redis 本身支持事務但不支持分佈式事務,不過我們可以通過 Redisson 框架實現分佈式事務的功能。

Redisson 框架支持redis單實例、redis哨兵、redis cluster、redis master-slave等各種部署架構,底層基於Netty NIO.

Github 地址:https://github.com/redisson/redisson

在這裏插入圖片描述

一般分佈式事務處理模式包括:2階段提交、3階段提交、TCC(Try-Confirm-Cancel)、可靠消息(消息隊列、數據庫表)、SAGAS長事務、補償性事務。

事務正確執行必須遵守的四個原則,江湖俗稱 ACID,即:

  • 原子性:要麼全部成功,要麼全部失敗
  • 一致性:事務必須始終保持系統處於一致的狀態,不管在任何給定的時間併發事務有多少。
  • 隔離型:同一時間僅有一個請求用於同一數據。
  • 持久性:在事務完成以後,該事務對數據庫所作的更改便持久的保存在數據庫之中,並不會被回滾

附錄:

1.5 分佈式緩存

我們知道Redis 最常用於分佈式緩存中,在講解之前先來看幾個分佈式緩存相關的概念:

  • 緩存雪崩
    緩存雪崩指的是所有緩存突然全部失效,所有請求都不再經過緩存而是直接請求數據庫導致數據庫壓力多大導致數據庫掛掉。
  • 緩存穿透
    緩存穿透是指所有的請求查詢緩存沒有,再查數據庫也沒有,如果每次請求都經過這兩步,效率很低。
  • 緩存預熱
    緩存預熱就是說當系統上線後,將相關的緩存數據直接加載到緩存系統

如何解決緩存雪崩?

1.6 Redis 的優點和缺點

Redis的優點在於

  • 源碼可讀性高,代碼質量很高
  • 支持持久化到磁盤
  • 支持事務
  • 所有操作都是原子性的
  • 支持多個數據庫

Redis 的缺點在於:

  • Redis 臨時申請內存,可能導致內存碎片
  • 單線程,難以利用多核特性
  • 每個數據庫數據隔離不能共享

1.7 Redis 的集羣方式

redis有三種集羣方式:主從複製模式,哨兵模式和Redis-Cluster集羣模式

1.8 什麼是髒讀、不可重複讀、幻讀?

  • 髒讀 : 一個事務讀取到了另一個事務未提交的數據操作結果。可能造成所有數據一起回滾!
  • 不可重複讀 :事務 T1 讀取某一數據後,事務 T2 對其做了修改,當事務 T1 再次讀該數據時得到與前一次不同的 值。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱爲是不可重複讀。
  • 幻讀 : 事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的數據或者缺少了第一次查 詢中出現的數據(並不要求兩次查詢的 SQL 語句相同)。這是因爲在兩次查詢過程中有另外一個事務插入數據造 成的

什麼是髒讀、不可重複讀、幻讀?

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