亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

分布式Redis深度歷險-復制

發布時間:2020-06-14 19:07:05 來源:網絡 閱讀:399 作者:Java筆記丶 欄目:編程語言

Redis深度歷險分為兩個部分,單機Redis和分布式Redis。

本文為分布式Redis深度歷險系列的第一篇,主要內容為Redis的復制功能。

Redis的復制功能的作用和大多數分布式存儲系統一樣,就是為了支持主從設計,主從設計的好處有以下幾點:

  • 讀寫分離,提高讀寫性能

  • 數據備份,減少數據丟失的風險

  • 高可用,避免單點故障

分布式Redis深度歷險-復制

舊版復制實現

Redis的復制主要分為同步和命令傳播兩個步驟:

同步可以理解為全量,是將主服務器某一時刻的所有數據全部同步到從服務器。

命令傳播可以理解為增量,當主服務器數據被修改時,主服務器向從服務器發送對應的數據修改命令。

?

同步

同步分為以下幾個步驟:

1.從服務器向主服務器發送SYNC命令(執行SLAVE OF命令的第一步也會執行SYNC

2.主服務器在收到從服務器命令時,會執行BGSAVE,也就是新開一個子進程將內存中的數據保存到RDB文件中。同時使用一個內存緩沖區記錄從現在開始執行的寫命令,該內存緩沖區的作用就是記錄RDB文件生成期間的增量。

3.向從服務器發送RDB文件

4.將緩沖區中的寫命令發送給從服務器

同步可以分為兩種情況,一種是從服務器第一次連接主服務器,另一種是從服務與主服務器的網絡鏈接斷開了,重新連上主服務器并重新同步。

?

命令傳播

命令傳播實現邏輯比較簡單,當主服務器執行了寫命令后,為了保證從服務器與主服務器數據的一致性,主服務器會將寫命令發送給從服務器,從服務器執行完收到的寫命令后其數據就能和主服務器保持一致了(當然會有延時),注意,從服務器對于客戶端來說是只讀的,因此從服務器的所有數據都是來自于主服務器的同步or命令傳播。

?

舊版復制存在的問題

假設Redis主從服務器之間的網絡環境不太可靠,我們來看看上述復制方法會出現什么問題。假設有主服務器A和從服務器B,主服務器中目前存在1-10000共一萬條數據。

1.初始連接,從服務器第一次從主服務器同步數據,同步完成后,從服務器也有1-10000共一萬條數據。

2.主服務器新增10001,10002兩條數據

3.通過命令傳播,從服務器也新增10001,10002兩條數據

4.這時候主從服務器之間的網絡斷開

5.主服務器新增數據10003,因為網絡斷開,所以從服務器感受不到數據變化

6.網絡恢復,從服務器重新連接上主服務器,并發送SYNC命令,進行同步操作

7.主服務器將所有數據發送給從服務器(1-10003)

從上述步驟中可以看到,當從服務器重新連接上主服務器時,會重新進行全量同步,造成大量不必要的IO開銷,如果網絡環境不穩定時,會導致主服務器一直將內存中的數據寫到磁盤再發送給從服務器。

?

新版復制實現

為了解決老版復制問題,Redis2.8對于復制功能進行了優化。實現如下:

1.主服務器會維護一個偏移量,每次向服務器傳播N個字節的數據時,該偏移量就會加上N,比如說一開始是0,接受到一條set key1 value1后,其偏移量就為13(真實偏移可能不是13,只是舉個例子)。//這里可能要看下代碼確認

2.從服務器也維護一個偏移量,當從服務器收到到主服務器的N個字節數據時,該偏移量會加上N。

3.主服務器維護一個固定大小的緩沖區,每次接受到客戶端寫命令后,都會將對應命令往這個緩沖區寫入。當寫入內容超出固定大小后,會覆蓋原來的數據。

4.主服務器有一個唯一id

5.從服務器連接上主服務時,會向主服務器發送上一次連接的主服務器的id以及偏移量,這里又分幾種情況:

  1. 如果從服務器沒傳id或者id與當前主服務器不匹配,那主服務器將傳送全量數據

  2. 如果從服務器的offset在緩沖區中不能找到(落后太多導致緩沖區已經被新數據覆蓋了),那也會進行全量同步

  3. 如果offset能在緩沖區找到,則主服務從offset開始,將緩沖區的數據依次發送給從服務器。(有做pipeline的優化嗎)

以上就是新版復制的大致思路,要注意的是,主服務器緩沖區的大小設置很關鍵,如果設置的太大會導致空間浪費,如果太小會導致網絡環境不好時,其退化為老版復制。

之前我就踩過這樣的坑:在上云時,redis集群在兩個不同機房,主從之前網絡環境不太穩定,而redis機器上存儲的value比較大,很容易就將緩沖區占滿導致每次全量同步,形成惡性循環,從服務器落后不可讀,主服務器不可寫(當從Redis落后太多時,主Redis將拒絕寫入,具體參數可以配置的,下文還會提到)

所以建議將緩沖區大小設置為平均重連間隔*每秒寫入數據量*2

?

主從心跳機制

從服務器默認會每秒一次的頻率向主服務器發送心跳:
REPLCONF A?K <replication_offset>
replication_offset代表從服務器當前的復制偏移量。

心跳有三個作用:

1.檢測主從服務器的網絡連接

2.實現min-slaves功能

3.檢測命令丟失

?

檢測主從服務器的網絡連接

主服務器會記錄從服務器上次發送心跳是什么時間,根據這個時間,我們能知道主從服務器之間的連接是不是出現了故障

?

實現min-slaves功能

Redis為了保證數據的安全性,可以配置當從服務器小于min-slaves-to-write個或者min-slaves-to-write個從服務器的延遲都大于等于min-slaves-max-lag時,主服務器拒絕寫。

?

檢測命令丟失

主從之間的復制,其實是以主服務器作為從服務器的客戶端來實現的(在Redis中,所有服務器之間的數據傳遞都是以該種方式)。假設主服務器向從服務器發送一條寫命令,但網絡出現異常,從服務器并沒有收到該命令。


這就會導致數據不一致的狀態(你可能想主服務器發送命令時,如果從沒返回失敗,進行重發不就好了嗎?如果說從成功執行了命令,但是再回復主的時候出現了問題,那主如果重發就會造成數據異常了)。所以主服務器會根據心跳信息來決定要發送的數據。看個例子:

初始,主服務器和從服務器偏移量都是100。

主服務器收到客戶端的寫命令,將偏移量改成110,同時向從服務器發送寫命令,但因網絡原因,從服務器并沒有收到,其偏移量仍然是100。主服務器根據心跳發現從服務器的偏移量是100落后于自己,所以會將100-110的數據進行重發。

?

看到這里,你可能對于上述方案的正確性感到質疑:在從服務器接收到100-110的數據前,它發送心跳包告訴主服務器自己當前偏移為100,然后接收到了100-110的數據。這時下個心跳還沒發出,主服務器認為從服務器落后于自己,再次發送100-110的數據,導致從服務器再次寫入100-110的數據,導致數據異常!

?

如果你有想到這個問題,說明你是有在認真思考了~

其實是不存在這種情況的,原因是redis是單線程的!記住單線程三個字,再回頭看一遍問題描述,相信你能想明白~

?


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亳州市| 象山县| 江油市| 东海县| 陈巴尔虎旗| 上高县| 临夏县| 闻喜县| 峨边| 措勤县| 乐安县| 顺义区| 潮安县| 孟津县| 朝阳县| 枝江市| 丹巴县| 澄迈县| 米泉市| 鲜城| 泽州县| 明溪县| 五台县| 亚东县| 阿拉尔市| 嵊州市| 河西区| 江安县| 巴彦淖尔市| 正镶白旗| 敦煌市| 宣化县| 绩溪县| 北海市| 毕节市| 邵阳市| 玉林市| 旅游| 周至县| 汶上县| 莱州市|