1崇决、RDB和AOF的優(yōu)缺點
RDB 模式優(yōu)點
RDB快照保存了某個時間點的數據,可以通過腳本執(zhí)行redis指令bgsave(非阻塞底挫,后臺執(zhí)行)或者save(會阻塞寫操作,不推薦)命令自定義時間點備份恒傻,可以保留多個備份,當出現問題可以恢復到不同時間點的版本,很適合備份,并且此文件格式也支持有不少第三方工具可以進行后續(xù)的數據分析建邓。
比如: 可以在最近的24小時內盈厘,每小時備份一次RDB文件,并且在每個月的每一天官边,也備份一個RDB文件沸手。這樣的話外遇,即使遇上問題,也可以隨時將數據集還原到不同的版本契吉。
RDB可以最大化Redis的性能臀规,父進程在保存 RDB文件時唯一要做的就是fork出一個子進程,然后這個子進程就會處理接下來的所有保存工作栅隐,父進程無須執(zhí)行任何磁盤工/0操作塔嬉。
RDB在大量數據,比如幾個G的數據,恢復的速度比AOF的快租悄。
RDB模式缺點
不能實時保存數據谨究,可能會丟失自上一次執(zhí)行RDB備份到當前的內存數據
如果你需要盡量避免在服務器故障時丟失數據,那么RDB不適合你泣棋。雖然Redis允許你設置不同的,保存點(save point)來控制保存RDB文件的頻率.但是胶哲,因為ROB文件需要保存整個數據集的狀態(tài),所以它并不是一個輕松的操作潭辈。因此你可能會至少5分鐘才保存一次RDB文件鸯屿。
在這種情況下,一旦發(fā)生故障停機把敢,你就可能會丟失好幾分鐘的數據寄摆。當數據量非常大的時候,從父進程fork子進程進行保存至RDB文件時需要一點時間修赞,可能是毫秒或者秒婶恼,取決于磁盤IO性能在數據集比較龐大時,fork()可能會非常耗時柏副,造成服務器在一定時間內停止處理客戶端﹔如果數據集非常巨大勾邦,并且CPU時間非常緊張的話,那么這種停止時間甚至可能會長達整整一秒或更久割择。
雖然 AOF重寫也需要進行fork()眷篇,但無論AOF重寫的執(zhí)行間隔有多長,數據的持久性都不會有任何損失荔泳。
AOF 模式優(yōu)點
數據安全性相對較高蕉饼,根據所使用的fsync策略(fsync是同步內存中redis所有已經修改的文件到存儲設備),默認是appendfsync everysec换可,即每秒執(zhí)行一次 fsync,在這種配置下椎椰,Redis 仍然可以保持良好的性能,并且就算發(fā)生故障停機沾鳄,也最多只會丟失一秒鐘的數據( fsync會在后臺線程執(zhí)行,所以主線程可以繼續(xù)努力地處理命令請求)由于該機制對日志文件的寫入操作采用的是append模式确憨,因此在寫入過程中不需要seek, 即使出現宕機現象译荞,也不會破壞日志文件中已經存在的內容瓤的。然而如果本次操作只是寫入了一半數據就出現了系統(tǒng)崩潰問題,不用擔心吞歼,在Redis下一次啟動之前圈膏,可以通過 redis-check-aof 工具來解決數據一致性的問題。
Redis可以在 AOF文件體積變得過大時篙骡,自動地在后臺對AOF進行重寫:重寫后的新AOF文件包含了恢復當前數據集所需的最小命令集合稽坤。整個重寫操作是絕對安全的,因為Redis在創(chuàng)建新 AOF文件的過程中糯俗,append模式不斷的將修改數據追加到現有的 AOF文件里面尿褪,即使重寫過程中發(fā)生停機,現有的 AOF文件也不會丟失得湘。而一旦新AOF文件創(chuàng)建完畢杖玲,Redis就會從舊AOF文件切換到新AOF文件,并開始對新AOF文件進行追加操作淘正。
AOF包含一個格式清晰摆马、易于理解的日志文件用于記錄所有的修改操作。事實上鸿吆,也可以通過該文件完成數據的重建囤采。AOF文件有序地保存了對數據庫執(zhí)行的所有寫入操作,這些寫入操作以Redis協(xié)議的格式保存惩淳,因此AOF文件的內容非常容易被人讀懂斑唬,對文件進行分析(parse)也很輕松。
導出(export)AOF文件也非常簡單:舉個例子黎泣,如果你不小心執(zhí)行了FLUSHALL.命令恕刘,但只要AOF文件未被重寫,那么只要停止服務器抒倚,移除 AOF文件末尾的FLUSHAL命令褐着,并重啟Redis ,就可以將數據集恢復到FLUSHALL執(zhí)行之前的狀態(tài)。
AOF 模式缺點
即使有些操作是重復的也會全部記錄托呕,AOF 的文件大小要大于 RDB 格式的文件
AOF 在恢復大數據集時的速度比 RDB 的恢復速度要慢
根據fsync策略不同,AOF速度可能會慢于RDB
bug 出現的可能性更多
2含蓉、master和slave同步過程
主從模式(master/slave),可以實現Redis數據的跨主機備份项郊。
程序端連接到高可用負載的VIP馅扣,然后連接到負載服務器設置的Redis后端real server,此模式不需要在程序里面配 置Redis服務器的真實IP地址着降,當后期Redis服務器IP地址發(fā)生變更只需要更改redis 相應的后端real server即可差油, 可避免更改程序中的IP地址設置。
主從復制特點
一個master可以有多個slave
一個slave只能有一個master
數據流向是單向的,master到slave
主從復制實現
Redis Slave 也要開啟持久化并設置和master同樣的連接密碼蓄喇,因為后期slave會有提升為master的可能,Slave 端切換master同步后會丟失之前的所有數據,而通過持久化可以恢復數據一旦某個Slave成為一個master的slave发侵,Redis Slave服務會清空當前redis服務器上的所有數據并將master的數據導入到自己的內存,但是如果只是斷開同步關系后,則不會刪除當前已經同步過的數據妆偏。
當配置Redis復制功能時刃鳄,強烈建議打開主服務器的持久化功能。否則的話钱骂,由于延遲等問題叔锐,部署的服務應該要避免自動啟動。
參考案例: 導致主從服務器數據全部丟失
在關閉主服務器上的持久化见秽,并同時開啟自動拉起進程的情況下愉烙,即便使用Sentinel來實現Redis的高可用性,也是非常危險的张吉。因為主服務器可能拉起得非吵萘海快,以至于Sentinel在配置的心跳時間間隔內沒有檢測到主服務器已被重啟肮蛹,然后還是會執(zhí)行上面的數據丟失的流程勺择。無論何時,數據安全都是極其重要的伦忠,所以應該禁止主服務器關閉持久化的同時自動啟動省核。
默認redis 狀態(tài)為master,需要轉換為slave角色并指向master服務器的IP+PORT+Password
REPLICAOF MASTER_IP PORT 指令可以啟用主從同步復制功能,早期版本使用 SLAVEOF 指令
配置redis主從(redis默認自身為主master)
在從節(jié)點上執(zhí)行
replicaof <masterhost IP> <port>
修改配置文件配置從節(jié)點
vim redis.conf
masterauth 123456
replicaof <masterip> <masterport>
requirepass 123456
1)從服務器連接主服務器昆码,發(fā)送PSYNC命令
2)主服務器接收到PSYNC命令后气忠,開始執(zhí)行BGSAVE命令生成RDB快照文件并使用緩沖區(qū)記錄此后執(zhí)行的所有
寫命令
3)主服務器BGSAVE執(zhí)行完后,向所有從服務器發(fā)送RDB快照文件赋咽,并在發(fā)送期間繼續(xù)記錄被執(zhí)行的寫命令
4)從服務器收到快照文件后丟棄所有舊數據旧噪,載入收到的快照至內存
5)主服務器快照發(fā)送完畢后,開始向從服務器發(fā)送緩沖區(qū)中的寫命令
6)從服務器完成對快照的載入,開始接收命令請求脓匿,并執(zhí)行來自主服務器緩沖區(qū)的寫命令
7)后期同步會先發(fā)送自己slave_repl_offset位置淘钟,只同步新增加的數據,不再全量同步
3陪毡、哨兵的使用和實現機制
Sentinel 進程是用于監(jiān)控redis集群中Master主服務器工作的狀態(tài)米母,在Master主服務器發(fā)生故障的時
候,可以實現Master和Slave服務器的切換毡琉。Sentinel節(jié)點應為奇數铁瞒,否則可能出現腦裂。
哨兵(Sentinel) 是一個分布式系統(tǒng)桅滋,可以在一個架構中運行多個哨兵(sentinel) 進程慧耍,這些進程使用流言
協(xié)議(gossip protocols)來接收關于Master主服務器是否下線的信息,并使用投票協(xié)議(Agreement
Protocols)來決定是否執(zhí)行自動故障遷移,以及選擇哪個Slave作為新的Master
每個哨兵(Sentinel)進程會向其它哨兵(Sentinel)、Master蜂绎、Slave定時發(fā)送消息栅表,以確認對方是否”活”
著笋鄙,如果發(fā)現對方在指定配置時間(可配置的)內未得到回應师枣,則暫時認為對方已離線,也就是所謂的”主
觀認為宕機” (主觀:是每個成員都具有的獨自的而且可能相同也可能不同的意識)萧落,英文名稱:Subjective
Down践美,簡稱SDOWN
有主觀宕機,對應的有客觀宕機找岖。當“哨兵群”中的多數Sentinel進程在對Master主服務器做出SDOWN
的判斷陨倡,并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下線
判斷许布,這種方式就是“客觀宕機”(客觀:是不依賴于某種意識而已經實際存在的一切事物)兴革,英文名稱是:
Objectively Down, 簡稱 ODOWN
通過一定的vote算法蜜唾,從剩下的slave從服務器節(jié)點中杂曲,選一臺提升為Master服務器節(jié)點,然后自動修
改相關配置袁余,并開啟故障轉移(failover)擎勘。
sentinel中的三個定時任務
每10秒每個sentinel寸master和slave執(zhí)行info
發(fā)現slave節(jié)點
確認主從關系
每2秒每個sentinel通過master節(jié)點的channel交換信息(pub/sub)
通過sentinel__:hello頻道交互
交互對節(jié)點的“看法”和自身信息
每1秒每個sentinel對其他sentinel和redis執(zhí)行ping
配置Sentinel
vim redis-sentinel.conf
bind 0.0.0.0
port 26379
daemonize yes
pidfile "redis-sentinel.pid"
logfile "sentinel_26379.log"
dir "/tmp" #工作目錄
sentinel myid 50547f34ed71fd48c197924969937e738a39975b #此行為啟動sentinel服務后自動生成
sentinel monitor mymaster 10.0.0.8 6379 2 #指定當前master服務器的地址和端口
# 主從集群名稱 masterip masterport
#2為法定人數限制(quorum),即有幾個sentinel認為master down了就進行故障轉移颖榜,一般此值是所有
sentinel節(jié)點(一般總數是>=3的 奇數,如:3,5,7等)的一半以上的整數值棚饵,比如,總數是3掩完,即
3/2=1.5噪漾,取整為2,是master的ODOWN客觀下線的依據
sentinel auth-pass mymaster 123456 #master的密碼,注意此行要在上面行的下面
sentinel down-after-milliseconds mymaster 30000 #(SDOWN)判斷所有節(jié)點的主觀下線的時
間且蓬,單位:毫秒欣硼,建議3000
sentinel parallel-syncs mymaster 1 #發(fā)生故障轉移后,同時向新master同步數據的slave數量缅疟,
數字越小總同步時間越長分别,但可以減輕新master的負載壓力
sentinel failover-timeout mymaster 180000 #所有slaves指向新的master所需的超時時間,單
位:毫秒
sentinel deny-scripts-reconfig yes #禁止修改腳本
logfile /var/log/redis/sentinel.log
#啟動哨兵#
redis-sentinel 配置文件
4存淫、redis cluster集群創(chuàng)建和使用
創(chuàng)建集群
原生命令(5版本)
redis-cli -a 123456 --cluster create 10.0.0.8:6379 10.0.0.18:6379 10.0.0.28:6379 10.0.0.18:6380 10.0.0.28:6380 10.0.0.8:6380 --cluster-replicas 1 #建立集群并設置主從 --cluster-replicas 1 表示master僅有一個從節(jié)點耘斩,這里前三個為主
redis-trib.rb 命令用法(3、4版本)
Redis 3和 4版本需要使用到集群管理工具redis-trib.rb桅咆,這個工具是redis官方推出的管理redis集群的
工具括授,集成在redis的源碼src目錄下,是基于redis提供的集群命令封裝成簡單、便捷荚虚、實用的操作工
具薛夜,redis-trib.rb是redis作者用ruby開發(fā)完成的,centos 7 系統(tǒng)yum安裝的ruby存在版本較低問題版述。
編譯安裝ruby環(huán)境
yum -y install gcc openssl-devel zlib-devel
wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.5.tar.gz
tar xf ruby-2.5.5.tar.gz
cd ruby-2.5.5
./configure
make -j 2 && make install
ruby -v
ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux]
#注意需要重新登錄
#修改redis-trib.rb連接redis的密碼
vim /usr/local/lib/ruby/gems/2.5.0/gems/redis-
4.1.3/lib/redis/client.rb
#ruby創(chuàng)建集群#
redis-trib.rb create --replicas 1 10.0.0.7:6379 10.0.0.17:6379 10.0.0.27:6379 10.0.0.7:6380 10.0.0.17:6380 10.0.0.27:6380
集群數據寫入腳本
#!/usr/bin/env python3
from rediscluster import RedisCluster
startup_nodes = [
{"host":"10.0.0.7", "port":6379},
{"host":"10.0.0.7", "port":6380},
{"host":"10.0.0.17", "port":6379},
{"host":"10.0.0.17", "port":6380},
{"host":"10.0.0.27", "port":6379},
{"host":"10.0.0.27", "port":6380}
]
redis_conn= RedisCluster(startup_nodes=startup_nodes,password='123456',
decode_responses=True)
for i in range(0, 10000):
redis_conn.set('key'+str(i),'value'+str(i))
print('key'+str(i)+':',redis_conn.get('key'+str(i)))