深入淺出聊聊 Redis 高級特性
Redis 數據結構
Redis 常用的數據類型主要有以下五種:
- String
- Hash
- List
- Set
- Sorted set
Redis 內部使用一個 redisObject 對象來表示所有的 key 和 value。
String 在 redis 內部存儲默認就是一個字符串,被 redisObject 所引用,當遇到 incr,decr 等操作時會轉成數值型進行計算,此時 redisObject 的 encoding 字段為int。
list 的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis 內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。
Hash 對應 Value 內部實際就是一個 HashMap,實際這里會有2種不同實現,這個 Hash 的成員比較少時 Redis 為了節省內存會采用類似一維數組的方式來緊湊存儲,而不會采用真正的 HashMap 結構,對應的 value redisObject 的 encoding 為 zipmap,當成員數量增大時會自動轉成真正的 HashMap,此時 encoding 為 ht。
Redis 存儲
Redis 提供了一系列不同的持久性選項:
- RDB 持久性以指定的時間間隔執行數據集的時間點快照。
- AOF 持久性會記錄服務器接收到的每個寫入操作,這些操作將在服務器啟動時再次執行,重建原始數據集。使用與Redis協議本身相同的格式以追加方式記錄命令。
RDB的優點:
- RDB是Redis數據的非常緊湊的單文件時間點表示。
- RDB文件非常適合備份。
RDB的缺點:
- 快照不是非常耐用。如果運行Redis的計算機停止運行,電源線出現故障,或者意外地終止了您的實例,寫入Redis的最新數據將丟失。
- 為了使用子進程在磁盤上保留RDB,RDB需要經常fork。如果數據集很大,Fork會很費時,并且可能導致Redis在幾毫秒內停止服務客戶端,或者如果數據集非常大并且CPU性能不佳,甚至會持續一秒。
Redis 需要將數據集轉儲到磁盤時,會發生以下情況:
- Redis fork。我們現在有一個子進程和一個父進程。
- 子進程開始將數據集寫入臨時RDB文件。
- 當子進程寫完新的RDB文件后,它會替換舊的。
AOF的優勢:
AOF日志是一種只能追加的日志,因此如果發生停電,也不會出現問題。
AOF的缺點:
- AOF文件通常比相同數據集的等效RDB文件大。
- 根據確切的fsync策略,AOF可能比RDB慢。
Redis將在磁盤上同步數據的次數。有三種選擇:
- 每當一個新命令被附加到AOF時,fsync。非常非常緩慢,非常安全。
- 每秒fsync。足夠快(在2.4可能與快照一樣快),并且如果發生災難,您可能會丟失1秒的數據。
- 永遠不要fsync,只需將您的數據交給操作系統即可。更快,不安全的方法。
日志重寫使用已用于快照的相同的寫入時復制技巧。這是如何工作的:
- Redis fork,所以現在我們有子進程和一個父進程。
- 子進程開始在臨時文件中寫入新的AOF
- 父進程將所有新的更改累積到內存緩沖區中
- 當子進程完成重寫文件時,父進程獲取信號,并在子進程生成的文件末尾追加內存緩沖區的內容。
- Redis自動將舊文件重命名為新文件,并開始將新數據附加到新文件中。
Redis 事務
Redis 提供的事務機制與傳統的數據庫事務有些不同,傳統數據庫事務必須維護以下特性:原子性(Atomicity),一致性(Consistency),隔離性(Isolation),持久性(Durability),簡稱ACID。
原子性(Atomicity)
Redis 本身提供的所有 API 都是原子操作。
但 Redis 在事務執行過程的錯誤情況做出了權衡取舍,那就是放棄了回滾。
Redis 官方文檔對此給出的解釋是:
1、Redis 操作失敗的原因只可能是語法錯誤或者錯誤的數據庫類型操作,這些都是在開發層面能發現的問題不會進入到生產環境,因此不需要回滾。
2、Redis 內部設計推崇簡單和高性能,因此不需要回滾能力。
一致性(Consistency)
一致性意味著事務結束后系統的數據依然保證一致。
Redis 舍棄了回滾的設計,基本上也就舍棄對數據一致性的有效保證。
隔離性(Isolation)
隔離性保證了在事務完成之前,該事務外部不能看到事務里的數據改變。
Redis 采用單線程設計,隔離性得到保證。
持久性(Durability)
Redis 一般情況下都只進行內存計算和操作,持久性無法保證。
但 Redis 也提供了2種數據持久化模式,RDB 和 AOF,RDB 的持久化操作與命令操作是不同步的,無法保證事務的持久性。而 AOF 模式意味著每條命令的執行都需要進行系統調用操作磁盤寫入文件,可以保證持久性,但會大大降低 Redis 的訪問性能。
Redis 主從
Redis的主從結構可以采用一主多從或者級聯結構:
全量同步
Redis全量復制一般發生在Slave初始化階段,這時Slave需要將Master上的所有數據都復制一份。
具體步驟如下:
1)從服務器連接主服務器,發送SYNC命令;
2)主服務器接收到SYNC命名后,開始執行BGSAVE命令生成RDB文件并使用緩沖區記錄此后執行的所有寫命令;
3)主服務器BGSAVE執行完后,向所有從服務器發送快照文件,并在發送期間繼續記錄被執行的寫命令;
4)從服務器收到快照文件后丟棄所有舊數據,載入收到的快照;
5)主服務器快照發送完畢后開始向從服務器發送緩沖區中的寫命令;
6)從服務器完成對快照的載入,開始接收命令請求,并執行來自主服務器緩沖區的寫命令
增量同步
Redis增量復制是指Slave初始化后開始正常工作時主服務器發生的寫操作同步到從服務器的過程。
增量復制的過程主要是主服務器每執行一個寫命令就會向從服務器發送相同的寫命令,從服務器接收并執行收到的寫命令。
Redis 場景
常見的 NoSQL 方案分為 4 類。
- K-V 存儲:解決關系數據庫無法存儲數據結構的問題,以 Redis 為代表。
- 文檔數據庫:解決關系數據庫強 schema 約束的問題,以 MongoDB 為代表。
- 列式數據庫:解決關系數據庫大數據場景下的 I/O 問題,以 HBase 為代表。
- 全文搜索引擎:解決關系數據庫的全文搜索性能問題,以 Elasticsearch 為代表。
緩存的架構設計要點:
緩存穿透是指緩存沒有發揮作用,業務系統雖然去緩存查詢數據,但緩存中沒有數據,業務系統需要再次去存儲系統查詢數據。
通常情況下有兩種情況:
- 1、存儲數據不存在
- 2、緩存數據生成耗費大量時間或者資源
緩存雪崩是指當緩存失效(過期)后引起系統性能急劇下降的情況。
緩存熱點的解決方案就是復制多份緩存副本,將請求分散到多個緩存服務器上,減輕緩存熱點導致的單臺緩存服務器壓力。
讀寫分離+多級緩存策略
首頁分流加載