自我介紹
我, redis ,內存數據庫,有著比 memcached 更強大的功能。現在已經是這個領域的頭把金交椅。
常規數據庫
這里所說的常規數據庫是指基于硬盤讀寫的數據庫,比如 Oracle , MySQL , Mongodb 等。基于硬盤讀寫的數據庫可以有效的保證數據的高可用性。這里的高可用性指的是操作系統或者數據庫崩潰之后,不會造成數據丟失,這也是對數據庫的最基本要求。
內存數據庫
基于硬盤讀寫的數據庫雖然可以保證數據的高可用性,但是讀寫速度比較慢,這也是磁盤 I/O的天然屬性。雖然切換固態硬盤之后,性能會有顯著提升,但是經濟成本也會隨之升高,而且固態硬盤使用壽命偏低。為了解決這個問題, Redis 做出了改變。 Redis 是基于內存進行讀寫的數據庫,把數據全部存儲在內存中,這樣就可以大幅提高數據的讀寫速度。
memcached
說到內存數據庫,不得不提 memcached , memcached 比 Redis 出現的更早,也是基于內存進行數據存儲。在十幾年前,大家通用的緩存方案就是 memcached 。 memcached 支持 Key-Value形式的數據存儲,但是只支持 String 類型的數據結構,不支持更復雜的數據結構,也不支持集群。
操作系統或者 memcached 重啟后數據就會丟失。這也是基于內存進行數據存儲的最大缺點。
Redis
Redis 繼承了 memcached 所有的優點,并改進了很多缺點。比如 Redis 也是基于內存進行數據操作,并且支持更多的數據類型,比如 List , Set 等。最最主要的,也是這篇文章的重點, Redis 支持數據高可用,也就是說 Redis 或者操作系統重啟之后,數據不會丟失。
Redis 在高可用這條路上所付出的努力,就像一個不斷努力進取的勵志青年。
單機持久化
眾所周知,放在內存中的數據是不穩定的。為了解決因為系統或者 Redis 重啟造成的數據丟失問題。 Redis 提供了兩種數據持久化方案。
- 快照備份把 Redis 數據庫中的數據,定時備份到磁盤中。當數據庫重啟的時候,可以通過定時備份到磁盤文件中的快照文件進行數據恢復。這樣 Redis 既保證了數據的讀寫速度,又保證了數據的高可用。
- AOF 同步寫快照備份有個缺點,就是會丟失一部分數據。比如在新的快照文件生成之前,系統發生了問題,那么最近一次快照之后的數據將丟失。 Redis 為了解決這個問題,提出了 AOF 解決方案。所謂的 AOF 就是將每次寫入數據的命令都以追加的方式記錄到文件中。這樣在系統出問題的時候,只要將這個文件中的命令全部重放一下就OK了。這樣就可以做到不丟數了。
但是如果數據寫入操作太多的話,會造成 AOF 文件過大,為了解決這個問題 Redis 提供了 AOF 自動壓縮功能,以及去重功能,這樣可以達到對文件體積大小進行優化的目的。

主從復制
上面的兩種持久化方案,對于單節點 Redis 來說,基本已經夠用了。但是我們的系統總是越做越大,要求越來越多。有的時候單節點 Redis 往往撐不住系統的訪問量。這種情況下 Redis 提供了主從模式。
所謂的主從模式就是一個主節點,負責讀和寫,一個從節點,負責將主節點的數據同步到從節點,這樣主從節點信息就是一致的。
注意:從節點不支持寫操作,但是可以支持讀操作。當其中任意一個點掛掉之后,數據不會損失。而且可以將讀的壓力分散到多個節點,支持更大的訪問量。

哨兵模式
對于主從模式,這里有個最大的痛點。當主節點掛掉后,從節點是不會自動升級為主節點的。也就是負責往 Redis 寫入的程序會報錯,但是讀操作不會有問題。這一點不太符合高可用的要求。為了解決發生故障,主節點自動切換的問題, Redis 又給大家提供了哨兵模式。
所謂的哨兵模式就是,提供三個哨兵節點(同樣是 Redis 實例,只不過不存儲數據),來監控主從模式下的所有 Redis 節點(真正存儲數據的節點)。客戶端程序通過哨兵節點獲取主節點信息。當主節點掛掉后,哨兵節點會自動將其中一個從節點升級為主節點,提供給客戶端程序執行寫入操作。當發生故障的主節點恢復后,會自動變為新的主節點的從節點。

集群模式
大家可能發現了,無論是主從復制模式,還是哨兵模式都沒有解決分布式寫的問題,也就是說到目前為止,所有的方案都只能往一個節點寫數據,數據存儲能力受單節點限制。哨兵模式僅僅解決了主從復制模式下,發生故障后不能自動切換的問題。
為了解決分布式寫的問題, Redis 提供了集群功能。
Redis 集群可以實現分布式寫。集群中的節點分為主節點和從節點。主節點負責數據的讀寫以及集群信息的維護,從節點負責同步主節點的信息。
Redis 集群利用數據分片的概念,將要操作的 Key 進行哈希計算,根據得到的結果決定這個 Key 應該存儲到那個主節點。這樣就可以利用多個主節點進行分布式寫操作。進行讀操作的時候也會先計算 Key 的哈希值,然后找到對應的主節點。

很遺憾的是,集群模式也不是百分百完美,比如 key 的批量操作會受限制,只有當操作的 key都位于一個槽位時才能進行操作。 還有 Keys 操作,只能在任一節點發生,不能 跨 節點。 其實這些所有缺點,都是因為分布式寫造成的,因為你把數據分別存到了不同的 Redis 節點。
總結
Redis 由單節點的持久化,到主從復制模式,再到哨兵模式,再到最后的集群模式。一路打怪升級,不斷的完善自己。