㈠ redis主從復制最好採用哪種結構
redis主從復制總結整理
主題Redis
Redis的主從復制策略是通過其持久化的rdb文件來實現的,其過程是先mp出rdb文件,將rdb文件全量傳輸給slave,然後再將mp後的操作實時同步到slave中。讓從伺服器(slave server)成為主伺服器(master server)的精確復製品。官方文檔ReplicationHowto中提到以下特點:
一個master支持多個slave,slave可以接受其他slave的連接,作為其他slave的master,從而形成一個master-slave的多級結構
復制功能不會阻塞主伺服器: 即使有一個或多個從伺服器正在進行初次同步, 主伺服器也可以繼續處理命令請求。復制功能不會阻塞從伺服器: 只要在redis.conf文件中進行了相應的設置, 即使從伺服器正在進行初次同步, 伺服器也可以使用舊版本的數據集來處理命令查詢。不過, 在從伺服器刪除舊版本數據集並載入新版本數據集的那段時間內, 連接請求會被阻塞。
復制被利用來提供可擴展性,比如可以將slave端用作數據冗餘,也可以將耗時的命令(比如sort)發往某些slave從而避免master的阻塞,另外也可以用slave做持久化,由從伺服器去執行持久化操作,這只需要將master的配置文件中的save指令注釋掉。
Redis 使用非同步復制。 從 Redis 2.8 開始, 從伺服器會以每秒一次的頻率向主伺服器報告復制流的處理進度。
復制功能的實現
redis的主從復制分為兩個階段:
1)同步操作:將從伺服器的資料庫狀態更新至主伺服器當前所處的資料庫狀態。
2)命令傳播:在主伺服器的資料庫狀態被修改,導致主從伺服器的資料庫狀態出現不一致時,讓主從伺服器重新回到一致狀態。
同步
當客戶端向從伺服器發送SLAVEOF命令, 要求從伺服器復制主伺服器時, 從伺服器首先需要執行同步操作, 也即是, 將從伺服器的資料庫狀態更新至主伺服器當前所處的資料庫狀態。
從伺服器對主伺服器的同步操作需要通過向主伺服器發送SYNC命令來完成, 以下是SYNC命令的執行步驟:
從伺服器向主伺服器發送SYNC命令。
收到SYNC命令的主伺服器執行BGSAVE命令, 在後台生成一個 RDB 文件, 並使用一個緩沖區記錄從現在開始執行的所有寫命令。
當主伺服器的BGSAVE命令執行完畢時, 主伺服器會將BGSAVE命令生成的 RDB 文件發送給從伺服器, 從伺服器接收並載入這個 RDB 文件, 將自己的資料庫狀態更新至主伺服器執行BGSAVE命令時的資料庫狀態。
主伺服器將記錄在緩沖區裡面的所有寫命令發送給從伺服器, 從伺服器執行這些寫命令, 將自己的資料庫狀態更新至主伺服器資料庫當前所處的狀態。
下圖展示了SYNC命令執行期間, 主從伺服器的通信過程:
命令傳播
在同步操作執行完畢之後, 主從伺服器兩者的資料庫達到一致狀態, 但這種一致並不是一成不變的。當主伺服器執行客戶端發送的寫命令時,主伺服器的資料庫就有可能會被修改, 並導致主從伺服器狀態不再一致。為了讓主從伺服器再次回到一致狀態,主伺服器需要對從伺服器執行命令傳播操作: 主伺服器會將自己執行的寫命令 —— 即造成主從伺服器不一致的那條寫命令發送給從伺服器執行, 當從伺服器執行了相同的寫命令之後, 主從伺服器將再次回到一致狀態。但是這樣的復制功能有缺陷:在主從伺服器斷線重連之後執行同步動作時,生成完整的RDB文件並且發送到從伺服器載入,但主從伺服器的資料庫狀態在斷線前基本上是一致的,不一致的部分只有斷線後主伺服器執行那一部分修改資料庫的命令,所以這時SYNC命令就非常浪費,因為生成RDB文件時一個非常消耗CPU、內存和IO資源的過程,發送RDB文件到從伺服器會佔用大量的網路帶寬資源,從伺服器在載入RDB文件的過程中會阻塞不會響應任何命令,所以大部分情況下執行SYNC命令是沒有必要也是非常不合理的。
為了解決2.8之前版本SYNC命令的性能問題,2.8版本設計了一個新的命令PSYNC,PSYNC命令分為完整重同步和部分重同步,完整重同步過程用於從伺服器初始化時初次復制的情況和SYNC命令基本一致,PSYNC則用於斷線後重新復制,在條件允許的情況下,它不會生成RDB文件,而是給從伺服器回復一個+Continue表示執行部分重同步,並且把從伺服器斷線後主伺服器執行的修改資料庫的命令發送到從伺服器,從伺服器執行這些命令同步資料庫。
部分重同步功能由下面幾個部分構成:
主伺服器的復制偏移量和從伺服器的復制偏移量:當主伺服器在向從伺服器進行命令同步時,主伺服器和從伺服器會各自記錄一個復制偏移量,當主從伺服器的資料庫狀態一致時這兩個復制偏移量是相同的,如果這兩個偏移量不一致說明當前主從伺服器的狀態不一致。
主伺服器的復制積壓緩沖區:復制積壓緩沖區是一個固定大小的FIFO隊列,當隊列已滿時會彈出最早插入的數據,在主伺服器進行命令傳播時會同時把命令放到緩沖區中,緩沖區包含兩部分數據,偏移量和位元組。在進行復制時從伺服器會將偏移量上報到主伺服器,主服務檢查當前偏移量是否還存在緩沖區中,如果存在進行部分重同步,如果不存在進行完整重同步。因為這個積壓緩沖區是一個固定大小的隊列,所以當從伺服器長時間斷線時,從伺服器的復制偏移量很可能已不再緩沖區中,這時候只能進行完整重同步。
伺服器的運行ID:初次同步時主伺服器會把ID發給從伺服器,從伺服器保存主伺服器ID,當斷線重連後,會把之前保存的主伺服器ID上報給主伺服器,主伺服器檢查從伺服器之前復制的主伺服器ID是否和自己的ID相同,如果相同,執行部分重同步,如果不同說明從伺服器之前記錄的狀態不是當前主伺服器,這時候需要執行完整重同步。
PSYNC命令實現
初始復制或者之前執行過SLAVEOF no one命令,執行完整重同步:發送PSYNC ? -1命令到主伺服器。如果從伺服器已經復制過某個主伺服器,在開始新復制時向主伺服器發送PSYNC <runid> <offset>命令,runid是上次復制的主伺服器id,offset是從伺服器的復制偏移量,主伺服器會根據這個兩個參數來決定做哪種同步,判斷伺服器id是否和本機相同,復制偏移量是否在緩沖區中,主伺服器有三種回復:
回復+FULLRESYNC <runid> <offset>執行完整重同步,從伺服器把offset當做初始復制偏移量
回復+CONTINUE,表示執行部分重同步,從伺服器等待主伺服器發送缺少的數據
回復-ERR,表示主伺服器版本低於2.8,不支持PSYNC命令
新版本復制過程:
設置主伺服器地址和埠,通過調用SAVEOF <master_ip> <master_port>命令。
建立套接字連接。
發送PING命令,檢查主從伺服器是否能夠正常處理命令。
身份驗證,從伺服器設置了masterauth並且主伺服器設置了requirepass是需要進行身份驗證。這兩個選項要麼都設置要麼都不設置,如果只設置了一個從伺服器向主伺服器發送命令時會報錯。
發送埠信息,通過執行命令REPLCONF listening-port <port-number>,向主伺服器發送從伺服器的監聽埠號。
同步,從伺服器向主伺服器發送PSYNC命令。
命令傳播,完成同步之後主伺服器會把之後執行的寫命令傳播到從伺服器保證主從伺服器的狀態一致。
心跳檢測
在命令傳播階段,從伺服器默認每秒一次的頻率向主伺服器發送命令:REPLCONF ACK <replication_offset>,replication_offset是從伺服器的復制偏移量,該命令有三個作用:
檢測從伺服器的網路連接狀態,檢測主從伺服器連接是否正常,如果主伺服器超過一定時間沒有收到從伺服器的REPLCONF ACK 命令,那麼它們的連接可能出了問題。
輔助實現min-slaves選項,min-slaves-to-write和min-slaves-max-lag兩個選項可以防止主伺服器在不安全的情況下執行寫命令,min-slaves-to-write 3 min-slaves-max-lag 10 表示如果從伺服器少於3個,或者3個從伺服器的延遲都大於10秒時,主伺服器拒絕寫命令。
檢測命令丟失,主伺服器接收到從伺服器的REPLCONF ACK 命令之後會檢查從伺服器的偏移量是否和主伺服器的一致,如果不一致會把積壓緩沖區中的從伺服器偏移量後面的命令發送到從伺服器。
關閉主伺服器持久化時,復制功能的數據安全
當配置Redis復制功能時,強烈建議打開主伺服器的持久化功能。 否則的話,由於延遲等問題,部署的服務應該要避免自動拉起。為了幫助理解主伺服器關閉持久化時自動拉起的危險性,參考一下以下會導致主從伺服器數據全部丟失的例子:
假設節點A為主伺服器,並且關閉了持久化。 並且節點B和節點C從節點A復制數據
節點A崩潰,然後由自動拉起服務重啟了節點A. 由於節點A的持久化被關閉了,所以重啟之後沒有任何數據
節點B和節點C將從節點A復制數據,但是A的數據是空的, 於是就把自身保存的數據副本刪除。
在關閉主伺服器上的持久化,並同時開啟自動拉起進程的情況下,即便使用Sentinel來實現Redis的高可用性,也是非常危險的。 因為主伺服器可能拉起得非常快,以至於Sentinel在配置的心跳時間間隔內沒有檢測到主伺服器已被重啟,然後還是會執行上面的數據丟失的流程。無論何時,數據安全都是極其重要的,所以應該禁止主伺服器關閉持久化的同時自動拉起。
只讀從伺服器
從 Redis 2.6 開始, 從伺服器支持只讀模式, 並且該模式為從伺服器的默認模式。
只讀模式由redis.conf文件中的slave-read-only選項控制, 也可以通過CONFIG SET命令來開啟或關閉這個模式。
只讀從伺服器會拒絕執行任何寫命令, 所以不會出現因為操作失誤而將數據不小心寫入到了從伺服器的情況。
即使從伺服器是只讀的,DEBUG和CONFIG等管理式命令仍然是可以使用的, 還是不應該將伺服器暴露給互聯網或者任何不可信網路。 不過, 使用redis.conf中的命令改名選項, 可以通過禁止執行某些命令來提升只讀從伺服器的安全性。
一些不重要的臨時數據, 仍然是可以保存在從伺服器上面的。 比如說, 客戶端可以在從伺服器上保存主伺服器的可達性信息, 從而實現故障轉移策略。所以仍然要讓一個從伺服器變得可寫。
從伺服器相關配置
如果主伺服器通過requirepass選項設置了密碼, 那麼為了讓從伺服器的同步操作可以順利進行, 我們也必須為從伺服器進行相應的身份驗證設置。
對於一個正在運行的伺服器, 可以使用客戶端輸入以下命令:
config set masterauth <password>
要永久地設置這個密碼, 那麼可以將它加入到配置文件中:
masterauth <password>
詳細的信息可以參考 Redis 源碼中附帶的redis.conf示例文件。
主伺服器只在有至少 N 個從伺服器的情況下,才執行寫操作
從 Redis 2.8 開始, 為了保證數據的安全性, 可以通過配置, 讓主伺服器只在有至少 N 個當前已連接從伺服器的情況下, 才執行寫命令。不過, 因為 Redis 使用非同步復制, 所以主伺服器發送的寫數據並不一定會被從伺服器接收到, 因此, 數據丟失的可能性仍然是存在的。以下是這個特性的運作原理:
從伺服器以每秒一次的頻率 PING 主伺服器一次, 並報告復制流的處理情況。
主伺服器會記錄各個從伺服器最後一次向它發送 PING 的時間。
用戶可以通過配置, 指定網路延遲的最大值min-slaves-max-lag, 以及執行寫操作所需的至少從伺服器數量min-slaves-to-write。
如果至少有min-slaves-to-write個從伺服器, 並且這些伺服器的延遲值都少於min-slaves-max-lag秒, 那麼主伺服器就會執行客戶端請求的寫操作。你可以將這個特性看作 CAP 理論中的 C 的條件放寬版本: 盡管不能保證寫操作的持久性, 但起碼丟失數據的窗口會被嚴格限制在指定的秒數中。
如果條件達不到min-slaves-to-write和min-slaves-max-lag所指定的條件, 那麼寫操作就不會被執行, 主伺服器會向請求執行寫操作的客戶端返回一個錯誤。
以下是這個特性的兩個選項和它們所需的參數:
min-slaves-to-write<numberofslaves>
min-slaves-max-lag<numberofseconds>
詳細的信息可以參考 Redis 源碼中附帶的redis.conf示例文件。
Redis可擴展集群搭建
1. 主動復制避開Redis復制缺陷。
既然Redis的復制功能有缺陷,不妨放棄Redis本身提供的復制功能,我們可以採用主動復制的方式來搭建我們的集群環境。所謂主動復制是指由業務端或者通過代理中間件對Redis存儲的數據進行雙寫或多寫,通過數據的多份存儲來達到與復制相同的目的,主動復制不僅限於 用在Redis集群上,目前很多公司採用主動復制的技術來解決MySQL主從之間復制的延遲問題,比如Twitter還專門開發了用於復制和分區的中間件gizzard(https://github.com/twitter/gizzard) 。
主動復制雖然解決了被動復制的延遲問題,但也帶來了新的問題,就是數據的一致性問題,數據寫2次或多次,如何保證多份數據的一致性呢?如果你的應用 對數據一致性要求不高,允許最終一致性的話,那麼通常簡單的解決方案是可以通過時間戳或者vector clock等方式,讓客戶端同時取到多份數據並進行校驗,如果你的應用對數據一致性要求非常高,那麼就需要引入一些復雜的一致性演算法比如Paxos來保證 數據的一致性,但是寫入性能也會相應下降很多。
通過主動復制,數據多份存儲我們也就不再擔心Redis單點故障的問題了,如果一組Redis集群掛掉,我們可以讓業務快速切換到另一組Redis上,降低業務風險。
2. 通過presharding進行Redis在線擴容。
通過主動復制我們解決了Redis單點故障問題,那麼還有一個重要的問題需要解決:容量規劃與在線擴容問題。我們前面分析過Redis的適用場景是全部數據存儲在內存中,而內存容量有限,那麼首先需要根據業務數據量進行初步的容量規劃,比如你的業務數據需 要100G存儲空間,假設伺服器內存是48G,至少需要3~4台伺服器來存儲。這個實際是對現有 業務情況所做的一個容量規劃,假如業務增長很快,很快就會發現當前的容量已經不夠了,Redis裡面存儲的數據很快就會超過物理內存大小,如何進行 Redis的在線擴容呢?Redis的作者提出了一種叫做presharding的方案來解決動態擴容和數據分區的問題,實際就是在同一台機器上部署多個Redis實例的方式,當容量不夠時將多個實例拆分到不同的機器上,這樣實際就達到了擴容的效果。
拆分過程如下:
在新機器上啟動好對應埠的Redis實例。
配置新埠為待遷移埠的從庫。
待復制完成,與主庫完成同步後,切換所有客戶端配置到新的從庫的埠。
配置從庫為新的主庫。
移除老的埠實例。
重復上述過程遷移好所有的埠到指定伺服器上。
以上拆分流程是Redis作者提出的一個平滑遷移的過程,不過該拆分方法還是很依賴Redis本身的復制功能的,如果主庫快照數據文件過大,這個復制的過程也會很久,同時會給主庫帶來壓力。所以做這個拆分的過程最好選擇為業務訪問低峰時段進行。
新浪微博的replication改進思路:
首先寫Redis的AOF文件,並對這個AOF文件按文件大小進行自動分割滾動,同時關閉Redis的Rewrite命令,然後會在業務低峰時間進行內存快照存儲,並把當前的AOF文件位置一起寫入到快照文件中,這樣我們可以使快照文件與AOF文件的位置保持一致性,這樣我們得到了系統某一時刻的內存快照,並且同時也能知道這一時刻對應的AOF文件的位置,那麼當從庫發送同步命令時,我們首先會把快照文件發送給從庫,然後從庫會取出該快照文件中存儲的AOF文件位置,並將該位置發給主庫,主庫會隨後發送該位置之後的所有命令,以後的復制就都是這個位置之後的增量信息了。
Redis的復制由於會使用快照持久化方式,所以如果Redis持久化方式選擇的是日誌追加方式(aof),那麼系統有可能在同一時刻既做aof日誌文件的同步刷寫磁碟,又做快照寫磁碟操作,這個時候Redis的響應能力會受到影響。所以如果選用aof持久化,則加從庫需要更加謹慎。
總結
Master最好不要做任何持久化工作,包括內存快照和AOF日誌文件,特別是不要啟用內存快照做持久化。
如果數據比較關鍵,某個Slave開啟AOF備份數據,策略為每秒同步一次。
為了主從復制的速度和連接的穩定性,Slave和Master最好在同一個區域網內。
盡量避免在壓力較大的主庫上增加從庫
為了Master的穩定性,主從復制不要用圖狀結構,用單向鏈表結構更穩定,即主從關系為:Master<–Slave1<–Slave2<–Slave3…….,這樣的結構也方便解決單點故障問題,實現Slave對Master的替換,也即,如果Master掛了,可以立即啟用Slave1做Master,其他不變。
㈡ 資料庫伺服器一台,使用Raid 0磁碟陣列,如何在不破壞原有磁碟數據的前提下對存儲空間擴容
有兩種方法:
第一種就是樓上說的,先把數據都備份出來,然後再重新分區或再加硬碟重建RAID0的陣列。
第二種方法,就是看你的伺服器陣列卡能不能支持在線擴容陣列的功能,如果可以,那樣是可以通過管理軟體,把新的硬碟添加進去。
㈢ oracle10g資料庫如何擴充表空間
oracle10g資料庫擴充表空間是通過增加數據文件的大小來實現的。
如果發現某個表空間存儲空間不足時,可以為表空間添加新的數據文件,擴展表空間大小。但是一般建議預先估計表空間所需的存儲空間大小,然後為它建立若干適當大小的數據文件。
以下是擴大TBS_TR_IND這個表空間的sql命令:
ALTER TABLESPACE TBS_TR_IND
ADD DATAFILE '/oradata/rTBS_TR_IND_002.dbf' --給rTBS_TR_IND_002.dbf這個數據文件增加32G空間
SIZE 32G
AUTOEXTEND OFF;
SQL> ALTER TABLESPACE TBS_EDS_DAT
ADD DATAFILE 'G:\datafile\TBS_EDS_DAT01.DBF' --給TBS_EDS_DAT01.DBF增加100M空間
SIZE 100M
㈣ 網站資料庫滿了怎麼辦
首先看資料庫文件所在硬碟的空間足不足,可以擴容解決這個問題;第二,什麼資料庫ms-sql的話可以刪除日誌文件,如果是oracel的話看看錶空間足不足,不足的話擴表空間。