成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

小林差點崩潰了,還好有主從復制

存儲 存儲軟件
主服務器可以進行讀寫操作,當發(fā)生寫操作時自動將寫操作同步給從服務器,而從服務器一般是只讀,并接受主服務器同步過來寫操作命令,然后執(zhí)行這條命令。

[[408729]]

本文轉載自微信公眾號「小林coding」,作者小林coding。轉載本文請聯(lián)系小林coding公眾號。

大家好,我是小林哥。

又來圖解 Redis 啦。

我在前兩篇已經給大家圖解了 AOF 和 RDB,這兩個持久化技術保證了即使在服務器重啟的情況下也不會丟失數據(或少量損失)。

不過,由于數據都是存儲在一臺服務器上,如果出事就完犢子了,比如:

  • 如果服務器發(fā)生了宕機,由于數據恢復是需要點時間,那么這個期間是無法服務新的請求的;
  • 如果這臺服務器的硬盤出現了故障,可能數據就都丟失了。

要避免這種單點故障,最好的辦法是將數據備份到其他服務器上,讓這些服務器也可以對外提供服務,這樣即使有一臺服務器出現了故障,其他服務器依然可以繼續(xù)提供服務。

多臺服務器要保存同一份數據,這里問題就來了。

這些服務器之間的數據如何保持一致性呢?數據的讀寫操作是否每臺服務器都可以處理?

Redis 提供了主從復制模式,來避免上述的問題。

這個模式可以保證多臺服務器的數據一致性,且主從服務器之間采用的是「讀寫分離」的方式。

主服務器可以進行讀寫操作,當發(fā)生寫操作時自動將寫操作同步給從服務器,而從服務器一般是只讀,并接受主服務器同步過來寫操作命令,然后執(zhí)行這條命令。

也就是說,所有的數據修改只在主服務器上進行,然后將最新的數據同步給從服務器,這樣就使得主從服務器的數據是一致的。

同步這兩個字說的簡單,但是這個同步過程并沒有想象中那么簡單,要考慮的事情不是一兩個。

我們先來看看,主從服務器間的第一次同步是如何工作的?

第一次同步

多臺服務器之間要通過什么方式來確定誰是主服務器,或者誰是從服務器呢?

我們可以使用 replicaof(Redis 5.0 之前使用 slaveof)命令形成主服務器和從服務器的關系。

比如,現在有服務器 A 和 服務器 B,我們在服務器 B 上執(zhí)行下面這條命令:

# 服務器 B 執(zhí)行這條命令

replicaof <服務器 A 的 IP 地址> <服務器 A 的 Redis 端口號>

接著,服務器 B 就會變成服務器 A 的「從服務器」,然后與主服務器進行第一次同步。

主從服務器間的第一次同步的過程可分為三個階段:

  • 第一階段是建立鏈接、協(xié)商同步;
  • 第二階段是主服務器同步數據給從服務器;
  • 第三階段是主服務器發(fā)送新寫操作命令給從服務器。

為了讓你更清楚了解這三個階段,我畫了一張圖。

接下來,我在具體介紹每一個階段都做了什么。

第一階段:建立鏈接、協(xié)商同步

執(zhí)行了 replicaof 命令后,從服務器就會給主服務器發(fā)送 psync 命令,表示要進行數據同步。

psync 命令包含兩個參數,分別是主服務器的 runID 和復制進度 offset。

  • runID,每個 Redis 服務器在啟動時都會自動生產一個隨機的 ID 來唯一標識自己。當從服務器和主服務器第一次同步時,因為不知道主服務器的 run ID,所以將其設置為 "?"。
  • offset,表示復制的進度,第一次同步時,其值為 -1。

主服務器收到 psync 命令后,會用 FULLRESYNC 作為響應命令返回給對方。

并且這個響應命令會帶上兩個參數:主服務器的 runID 和主服務器目前的復制進度 offset。從服務器收到響應后,會記錄這兩個值。

FULLRESYNC 響應命令的意圖是采用全量復制的方式,也就是主服務器會把所有的數據都同步給從服務器。

所以,第一階段的工作時為了全量復制做準備。

那具體怎么全量同步呀呢?我們可以往下看第二階段。

第二階段:主服務器同步數據給從服務器

接著,主服務器會執(zhí)行 bgsave 命令來生成 RDB 文件,然后把文件發(fā)送給從服務器。

從服務器收到 RDB 文件后,會先清空當前的數據,然后載入 RDB 文件。

這里有一點要注意,主服務器生成 RDB 這個過程是不會阻塞主線程的,也就是說 Redis 依然可以正常處理命令。

但是這期間的寫操作命令并沒有記錄到剛剛生成的 RDB 文件中,這時主從服務器間的數據就不一致了。

那么為了保證主從服務器的數據一致性,主服務器會將在 RDB 文件生成后收到的寫操作命令,寫入到 replication buffer 緩沖區(qū)里。

第三階段:主服務器發(fā)送新寫操作命令給從服務器

在主服務器生成的 RDB 文件發(fā)送后,然后將 replication buffer 緩沖區(qū)里所記錄的寫操作命令發(fā)送給從服務器,然后從服務器重新執(zhí)行這些操作。

至此,主從服務器的第一次同步的工作就完成了。

命令傳播

主從服務器在完成第一次同步后,雙方之間就會維護一個 TCP 連接。

后續(xù)主服務器可以通過這個連接繼續(xù)將寫操作命令傳播給從服務器,然后從服務器執(zhí)行該命令,使得與主服務器的數據庫狀態(tài)相同。

而且這個連接是長連接的,目的是避免頻繁的 TCP 連接和斷開帶來的性能開銷。

上面的這個過程被稱為基于長連接的命令傳播,通過這種方式來保證第一次同步后的主從服務器的數據一致性。

分攤主服務器的壓力

在前面的分析中,我們可以知道主從服務器在第一次數據同步的過程中,主服務器會做兩件耗時的操作:生成 RDB 文件和傳輸 RDB 文件。

主服務器是可以有多個從服務器的,如果從服務器數量非常多,而且都與主服務器進行全量同步的話,就會帶來兩個問題:

  • 由于是通過 bgsave 命令來生成 RDB 文件的,那么主服務器就會忙于使用 fork() 創(chuàng)建子進程,如果主服務器的內存數據非大,在執(zhí)行 fork() 函數時是會阻塞主線程的,從而使得 Redis 無法正常處理請求;
  • 傳輸 RDB 文件會占用主服務器的網絡帶寬,會對主服務器響應命令請求產生影響。

這種情況就好像,剛創(chuàng)業(yè)的公司,由于人不多,所以員工都歸老板一個人管,但是隨著公司的發(fā)展,人員的擴充,老板慢慢就無法承擔全部員工的管理工作了。

要解決這個問題,老板就需要設立經理職位,由經理管理多名普通員工,然后老板只需要管理經理就好。

Redis 也是一樣的,從服務器可以有自己的從服務器,我們可以把擁有從服務器的從服務器當作經理角色,它不僅可以接收主服務器的同步數據,自己也可以同時作為主服務器的形式將數據同步給從服務器,組織形式如下圖:

通過這種方式,主服務器生成 RDB 和傳輸 RDB 的壓力可以分攤到充當經理角色的從服務器。

那具體怎么做到的呢?

其實很簡單,我們在「從服務器」上執(zhí)行下面這條命令,使其作為目標服務器的從服務器:

replicaof <目標服務器的IP> 6379

此時如果目標服務器本身也是「從服務器」,那么該目標服務器就會成為「經理」的角色,不僅可以接受主服務器同步的數據,也會把數據同步給自己旗下的從服務器,從而減輕主服務器的負擔。

增量復制

主從服務器在完成第一次同步后,就會基于長連接進行命令傳播。

可是,網絡總是不按套路出牌的嘛,說延遲就延遲,說斷開就斷開。

如果主從服務器間的網絡連接斷開了,那么就無法進行命令傳播了,這時從服務器的數據就沒辦法和主服務器保持一致了,客戶端就可能從「從服務器」讀到舊的數據。

那么問題來了,如果此時斷開的網絡,又恢復正常了,要怎么繼續(xù)保證主從服務器的數據一致性呢?

在 Redis 2.8 之前,如果主從服務器在命令同步時出現了網絡斷開又恢復的情況,從服務器就會和主服務器重新進行一次全量復制,很明顯這樣的開銷太大了,必須要改進一波。

所以,從 Redis 2.8 開始,網絡斷開又恢復后,從主從服務器會采用增量復制的方式繼續(xù)同步,也就是只會把網絡斷開期間主服務器接收到的寫操作命令,同步給從服務器。

網絡恢復后的增量復制過程如下圖:

主要有三個步驟:

  • 從服務器在恢復網絡后,會發(fā)送 psync 命令給主服務器,此時的 psync 命令里的 offset 參數不是 -1;
  • 主服務器收到該命令后,然后用 CONTINUE 響應命令告訴從服務器接下來采用增量復制的方式同步數據;
  • 然后主服務將主從服務器斷線期間,所執(zhí)行的寫命令發(fā)送給從服務器,然后從服務器執(zhí)行這些命令。

那么關鍵的問題來了,主服務器怎么知道要將哪些增量數據發(fā)送給從服務器呢?

答案藏在這兩個東西里:

  • repl_backlog_buffer,是一個「環(huán)形」緩沖區(qū),用于主從服務器斷連后,從中找到差異的數據;
  • replication offset,標記上面那個緩沖區(qū)的同步進度,主從服務器都有各自的偏移量,主服務器使用 master_repl_offset 來記錄自己「寫」到的位置,從服務器使用 slave_repl_offset 來記錄自己「讀」到的位置。

那repl_backlog_buffer 緩沖區(qū)是什么時候寫入的呢?

在主服務器進行命令傳播時,不僅會將寫命令發(fā)送給從服務器,還會將寫命令寫入到 repl_backlog_buffer 緩沖區(qū)里,因此 這個緩沖區(qū)里會保存著最近傳播的寫命令。

網絡斷開后,當從服務器重新連上主服務器時,從服務器會通過 psync 命令將自己的復制偏移量 slave_repl_offset 發(fā)送給主服務器,主服務器根據自己的 master_repl_offset 和 slave_repl_offset 之間的差距,然后來決定對從服務器執(zhí)行哪種同步操作:

  • 如果判斷出從服務器要讀取的數據還在 repl_backlog_buffer 緩沖區(qū)里,那么主服務器將采用增量同步的方式;
  • 相反,如果判斷出從服務器要讀取的數據已經不存在

repl_backlog_buffer 緩沖區(qū)里,那么主服務器將采用全量同步的方式。

當主服務器在 repl_backlog_buffer 中找到主從服務器差異(增量)的數據后,就會將增量的數據寫入到 replication buffer 緩沖區(qū),這個緩沖區(qū)我們前面也提到過,它是緩存將要傳播給從服務器的命令。

repl_backlog_buffer 緩行緩沖區(qū)的默認大小是 1M,并且由于它是一個環(huán)形緩沖區(qū),所以當緩沖區(qū)寫滿后,主服務器繼續(xù)寫入的話,就會覆蓋之前的數據。

因此,當主服務器的寫入速度遠超于從服務器的讀取速度,緩沖區(qū)的數據一下就會被覆蓋。

那么在網絡恢復時,如果從服務器想讀的數據已經被覆蓋了,主服務器就會采用全量同步,這個方式比增量同步的性能損耗要大很多。

因此,為了避免在網絡恢復時,主服務器頻繁地使用全量同步的方式,我們應該調整下 repl_backlog_buffer 緩沖區(qū)大小,盡可能的大一些,減少出現從服務器要讀取的數據被覆蓋的概率,從而使得主服務器采用增量同步的方式。

那 repl_backlog_buffer 緩沖區(qū)具體要調整到多大呢?

repl_backlog_buffer 最小的大小可以根據這面這個公式估算。

我來解釋下這個公式的意思:

  • second 為從服務器斷線后重新連接上主服務器所需的平均 時間(以秒計算)。
  • write_size_per_second 則是主服務器平均每秒產生的寫命令數據量大小。

舉個例子,如果主服務器平均每秒產生 1 MB 的寫命令,而從服務器斷線之后平均要 5 秒才能重新連接主服務器。

那么 repl_backlog_buffer 大小就不能低于 5 MB,否則新寫地命令就會覆蓋舊數據了。

當然,為了應對一些突發(fā)的情況,可以將 repl_backlog_buffer 的大小設置為此基礎上的 2 倍,也就是 10 MB。

關于 repl_backlog_buffer 大小修改的方法,只需要修改配置文件里下面這個參數項的值就可以。

  1. repl-backlog-size 1mb 

總結

主從復制共有三種模式:全量復制、基于長連接的命令傳播、增量復制。

主從服務器第一次同步的時候,就是采用全量復制,此時主服務器會兩個耗時的地方,分別是生成 RDB 文件和傳輸 RDB 文件。為了避免過多的從服務器和主服務器進行全量復制,可以把一部分從服務器升級為「經理角色」,讓它也有自己的從服務器,通過這樣可以分攤主服務器的壓力。

第一次同步完成后,主從服務器都會維護著一個長連接,主服務器在接收到寫操作命令后,就會通過這個連接將寫命令傳播給從服務器,來保證主從服務器的數據一致性。

如果遇到網絡斷開,增量復制就可以上場了,不過這個還跟 repl_backlog_size 這個大小有關系。

如果它配置的過小,主從服務器網絡恢復時,可能發(fā)生「從服務器」想讀的數據已經被覆蓋了,那么這時就會導致主服務器采用全量復制的方式。所以為了避免這種情況的頻繁發(fā)生,要調大這個參數的值,以降低主從服務器斷開后全量同步的概率。

參考資料

《Redis核心技術與實戰(zhàn)》

《Redis設計與實現》

 

《Redis源碼分析》

 

責任編輯:武曉燕 來源: 小林coding
相關推薦

2023-03-19 22:38:12

邏輯復制PostgreSQL

2023-03-19 11:53:27

2023-09-24 14:32:15

2023-07-03 08:57:45

Master服務TCP

2024-03-01 18:33:59

MySQL節(jié)點數據

2021-06-08 07:48:27

MySQL主從配置

2024-07-04 08:00:24

2025-02-10 10:55:16

2023-05-11 08:08:18

MySQL主從復制

2023-12-25 08:02:09

2021-05-20 06:49:45

MongoDB高可用數據庫

2022-12-20 08:46:41

MySQL主從復制

2025-01-15 15:47:36

2017-10-11 15:40:20

MySQL主從復制拓撲結構

2017-09-05 16:00:49

MySQL主從復制備份

2021-03-19 11:33:42

MySQL數據庫備份

2023-02-27 07:33:14

MySQL數據庫服務器

2021-01-12 09:03:17

MySQL復制半同步

2024-07-04 17:22:23

2017-06-23 22:00:13

MySqlsslcentos
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品九九| 国产精品久久久久久久久免费 | 国产91网址 | 成人精品国产免费网站 | av一区二区三区在线观看 | 九色porny自拍视频 | 国产高清视频在线观看 | 久久毛片 | 亚洲一区国产 | 九九国产在线观看 | 亚洲精品欧美 | 国产精品一区久久久 | www精品美女久久久tv | 欧美中文字幕在线观看 | 成人国产一区二区三区精品麻豆 | 激情六月丁香 | 国产欧美日韩一区 | 国产激情精品视频 | 一级免费毛片 | 欧美一级黄色免费看 | 日韩午夜在线观看 | 国产免费一区二区三区 | 在线免费观看色 | a级片在线观看 | 日本免费一区二区三区四区 | 国产精品自拍视频 | 亚洲深夜福利 | 成人免费视屏 | 亚洲精选一区二区 | 久久国产精品一区二区三区 | 国产精品一区二区久久 | 日韩一级免费电影 | 91精品久久久久 | 久久久久久久久久一区二区 | 一级毛毛片 | 精品久久久久久久久久久下田 | 欧美激情精品久久久久 | 久久视频精品 | 日韩www | 精品免费国产一区二区三区四区 | 超碰人人爱 |