redis-高级特性
文章目錄
- 1. 主從復(fù)制
- 1.1 主從復(fù)制的特點(diǎn)
- 1.2 如何配置主從服務(wù)器
- 1.3 Redis主從復(fù)制是如何工作的
- 1.4 只讀從服務(wù)器
- 1.5 注意
- 2. redis的持久化
- 2.1 快照RDB(snapshoting)
- 2.2 AOF(Append Only File)
- 如何選擇使用哪種持久化方式?
- 3. 內(nèi)存優(yōu)化
- 3.1 虛擬內(nèi)存
- 3.2 設(shè)置maxmemory
- 3.3 盡可能使用散列表(hashes)
- 4. 用redis實(shí)現(xiàn)分布式鎖
- 4.1 單機(jī)Redis的分布式鎖
- 4.2 集群環(huán)境下redis的分布式鎖
1. 主從復(fù)制
1.1 主從復(fù)制的特點(diǎn)
redis的主從復(fù)制配置十分簡(jiǎn)單,它可以使從服務(wù)器是主服務(wù)器的完全拷貝,有以下幾個(gè)特點(diǎn):
1.2 如何配置主從服務(wù)器
另外你也可以調(diào)用SLAVEOF命令,主服務(wù)器就會(huì)開(kāi)始與從服務(wù)器同步。
2. 然后可通過(guò)role命令(或者info命令)查看結(jié)果
(slave服務(wù)運(yùn)行在6378端口,master服務(wù)運(yùn)行在6379端口)
此時(shí)可以在master設(shè)置key,在slave上即可get到該key值
1.3 Redis主從復(fù)制是如何工作的
? ? ? ?如果你設(shè)置了一個(gè)從服務(wù)器,在連接時(shí)它發(fā)送了一個(gè)SYNC命令,不管它是第一次連接還是再次連接都沒(méi)有關(guān)系。然后主服務(wù)器開(kāi)始后臺(tái)存儲(chǔ),并且開(kāi)始緩存新連接進(jìn)來(lái)的修改數(shù)據(jù)的命令。當(dāng)后臺(tái)存儲(chǔ)完成后,主服務(wù)器把數(shù)據(jù)文件發(fā)送到從服務(wù)器,從服務(wù)器將其保存在磁盤(pán)上,然后加載到內(nèi)存中。然后主服務(wù)器把剛才緩存的命令發(fā)送到從服務(wù)器。這是作為命令流來(lái)完成的,并且和Redis協(xié)議本身格式相同。
? ? ? ?你可以通過(guò)telnet自己嘗試一下。在Redis服務(wù)器工作時(shí)連接到Redis端口,發(fā)送SYNC命令,會(huì)看到一個(gè)批量的傳輸,并且主服務(wù)器接收的每一個(gè)命令都會(huì)通過(guò)telnet會(huì)話重新發(fā)送一遍。
? ? ? ?當(dāng)主從服務(wù)器之間的連接由于某些原因斷開(kāi)時(shí),從服務(wù)器可以自動(dòng)進(jìn)行重連接。當(dāng)有多個(gè)從服務(wù)器同時(shí)請(qǐng)求同步時(shí),主服務(wù)器只進(jìn)行一個(gè)后臺(tái)存儲(chǔ)。
? ? ? ?當(dāng)連接斷開(kāi)又重新連上之后,一般都會(huì)進(jìn)行一個(gè)完整的重新同步,但是從Redis2.8開(kāi)始,重新連接之后可以從中斷處繼續(xù)進(jìn)行復(fù)制,而不必重新同步。
1.4 只讀從服務(wù)器
? ? ? ?從Redis 2.6開(kāi)始,從服務(wù)器支持只讀模式,并且是默認(rèn)模式。向從服務(wù)器寫(xiě)入命令會(huì)報(bào)錯(cuò)誤:
(error) READONLY You can't write against a read only slave.這個(gè)行為是由Redis.conf文件中的slave-read-only 參數(shù)控制的,可以在運(yùn)行中通過(guò)CONFIG SET來(lái)啟用或者禁用。
? ? ? ?只讀的從服務(wù)器會(huì)拒絕所有寫(xiě)命令,所以對(duì)從服務(wù)器不會(huì)有誤寫(xiě)操作。但這不表示可以把從服務(wù)器實(shí)例暴露在危險(xiǎn)的網(wǎng)絡(luò)環(huán)境下,因?yàn)橄馜EBUG或者CONFIG這樣的管理命令還是可以運(yùn)行的。不過(guò)你可以通過(guò)使用rename-command命令來(lái)為這些命令改名來(lái)增加安全性。
? ? ? ?注意只讀限制還可以被還原,使得從服務(wù)器還可以進(jìn)行寫(xiě)操作。雖然當(dāng)主從服務(wù)器進(jìn)行重新同步或者從服務(wù)器重啟后,這些寫(xiě)操作都會(huì)失效,還是有一些使用場(chǎng)景會(huì)想從服務(wù)器中寫(xiě)入臨時(shí)數(shù)據(jù)的,但將來(lái)這個(gè)特性可能會(huì)被去掉。
1.5 注意
- 在做主從同步時(shí),如果主服務(wù)器關(guān)閉持久化并允許自動(dòng)重啟,在主服務(wù)器意外崩潰時(shí)可能導(dǎo)致所有服務(wù)器的數(shù)據(jù)都被清空。
- 可以配置限制有N個(gè)以上從服務(wù)器才允許對(duì)主服務(wù)器寫(xiě)入,如果條件不滿足,主服務(wù)器會(huì)拒絕寫(xiě)操作并返回一個(gè)錯(cuò)誤。
- 主從模式的升級(jí)——哨兵模式
? ? ? ?Redis的哨兵模式是以主從模式為基礎(chǔ)的,所以說(shuō),主從模式擁有的一些缺點(diǎn),在哨兵模式下也具有。哨兵模式主要是監(jiān)控Master主服務(wù)器的運(yùn)行情況,當(dāng)然也會(huì)監(jiān)控Slave從服務(wù)器的運(yùn)行情況,如果Master主服務(wù)器發(fā)生了故障,該模式可以保證Slave從服務(wù)器順利升級(jí)為Master主服務(wù)器繼續(xù)提供服務(wù),以此提高系統(tǒng)的高可用性。雖然哨兵模式比主從模式提高了不少系統(tǒng)的高可用性,但是該模式不能水平擴(kuò)容,不能動(dòng)態(tài)的增、刪節(jié)點(diǎn),這也是限制哨兵模式廣泛應(yīng)用的主要原因。Redis也看到了這個(gè)情況,所在在Redis的3.x以后的版本提供了一個(gè)更加強(qiáng)大集群模式,那就是Cluster集群模式
2. redis的持久化
2.1 快照RDB(snapshoting)
? ? ? ?快照是默認(rèn)的持久化方式。這種方式將內(nèi)存中的數(shù)據(jù)以快照的方式寫(xiě)入到磁盤(pán)的二進(jìn)制文件中,默認(rèn)的文件名為dump.rdb。我們可以配置redis在n秒內(nèi)如果超過(guò)m個(gè)key就自動(dòng)做快照:
save 900 1 # 900 秒內(nèi)如果至少有 1 個(gè) key 的值變化,則保存 save 300 10 # 300 秒內(nèi)如果至少有 10 個(gè) key 的值變化,則保存 save 60 10000 # 60 秒內(nèi)如果至少有 10000 個(gè) key 的值變化,則保存# 默認(rèn)情況下,如果 redis 最后一次的后臺(tái)保存失敗,redis 將停止接受寫(xiě)操作, # 這樣以一種強(qiáng)硬的方式讓用戶知道數(shù)據(jù)不能正確的持久化到磁盤(pán), # 否則就會(huì)沒(méi)人注意到災(zāi)難的發(fā)生。 # # 如果后臺(tái)保存進(jìn)程重新啟動(dòng)工作了,redis 也將自動(dòng)的允許寫(xiě)操作。 # # 然而你要是安裝了靠譜的監(jiān)控,你可能不希望 redis 這樣做,那你就改成 no 好了。 stop-writes-on-bgsave-error yes# 是否在 dump .rdb 數(shù)據(jù)庫(kù)的時(shí)候使用 LZF 壓縮字符串 # 默認(rèn)都設(shè)為 yes # 如果你希望保存子進(jìn)程節(jié)省點(diǎn) cpu ,你就設(shè)置它為 no , # 不過(guò)這個(gè)數(shù)據(jù)集可能就會(huì)比較大 rdbcompression yes# 是否校驗(yàn)rdb文件 rdbchecksum yes# 設(shè)置 dump 的文件位置 dbfilename dump.rdb# 工作目錄 # 例如上面的 dbfilename 只指定了文件名, # 但是它會(huì)寫(xiě)入到這個(gè)目錄下。這個(gè)配置項(xiàng)一定是個(gè)目錄,而不能是文件名。 dir ./? ? ? ?你也可以通過(guò)調(diào)用 SAVE或者 BGSAVE , 手動(dòng)讓 Redis 進(jìn)行數(shù)據(jù)集保存操作。它們倆的區(qū)別是save會(huì)直接在主進(jìn)程中執(zhí)行備份(此時(shí)主進(jìn)程阻塞,就相當(dāng)于此時(shí)redis不能提供服務(wù)了),bgsave會(huì)啟動(dòng)一個(gè)子進(jìn)程執(zhí)行備份操作,而父進(jìn)程繼續(xù)提供服務(wù)。
快照RDB的優(yōu)點(diǎn)
- RDB是一個(gè)非常緊湊的文件,它保存了某個(gè)時(shí)間點(diǎn)的數(shù)據(jù)集,非常適用于數(shù)據(jù)集的備份,比如你可以在每個(gè)小時(shí)報(bào)保存一下過(guò)去24小時(shí)內(nèi)的數(shù)據(jù),同時(shí)每天保存過(guò)去30天的數(shù)據(jù),這樣即使出了問(wèn)題你也可以根據(jù)需求恢復(fù)到不同版本的數(shù)據(jù)集.
- RDB是一個(gè)緊湊的單一文件,很方便傳送到另一個(gè)遠(yuǎn)端數(shù)據(jù)中心(可以加密),非常適用于災(zāi)難恢復(fù).
- RDB在保存RDB文件時(shí)父進(jìn)程唯一需要做的就是fork出一個(gè)子進(jìn)程,接下來(lái)的工作全部由子進(jìn)程來(lái)做,父進(jìn)程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
- 與AOF相比,在恢復(fù)大的數(shù)據(jù)集的時(shí)候,RDB方式會(huì)更快一些.
快照RDB的缺點(diǎn)
- 如果你希望在redis意外停止工作(例如電源中斷)的情況下丟失的數(shù)據(jù)最少的話,那么RDB不適合你,由于快照方式是在一定時(shí)間間隔內(nèi)做一次快照,如果redis意外down掉的話,就會(huì)丟失最后一次快照后的所有修改。.雖然你可以配置不同的save時(shí)間點(diǎn)(例如每隔5分鐘并且對(duì)數(shù)據(jù)集有100個(gè)寫(xiě)的操作),是Redis要完整的保存整個(gè)數(shù)據(jù)集是一個(gè)比較繁重的工作,你通常會(huì)每隔5分鐘或者更久做一次完整的保存,萬(wàn)一在Redis意外宕機(jī),你可能會(huì)丟失幾分鐘的數(shù)據(jù).
- RDB 需要經(jīng)常fork子進(jìn)程來(lái)保存數(shù)據(jù)集到硬盤(pán)上,當(dāng)數(shù)據(jù)集比較大的時(shí)候,fork的過(guò)程是非常耗時(shí)的,可能會(huì)導(dǎo)致Redis在一些毫秒級(jí)內(nèi)不能響應(yīng)客戶端的請(qǐng)求.如果數(shù)據(jù)集巨大并且CPU性能不是很好的情況下,這種情況會(huì)持續(xù)1秒,AOF也需要fork,但是你可以調(diào)節(jié)重寫(xiě)日志文件的頻率來(lái)提高數(shù)據(jù)集的耐久度.
2.2 AOF(Append Only File)
aof比快照有更好的持久化性,redis會(huì)將每一個(gè)收到的命令都通過(guò)write函數(shù)追加到文件(默認(rèn)文件名為appendonly.aof)中,redis重啟時(shí)會(huì)通過(guò)重新執(zhí)行文件中保存的命令來(lái)在內(nèi)存中重建整個(gè)數(shù)據(jù)庫(kù)的內(nèi)容。
appendonly yes 啟用持久化方式由于os(Operating System )會(huì)在內(nèi)核中緩存write做的修改,所以可能不是立即寫(xiě)到磁盤(pán)上。這樣aof方式的持久化也是有可能丟失部分修改。可以通過(guò)配置文件告訴redis我們想要通過(guò)fsync函數(shù)強(qiáng)制os寫(xiě)入到磁盤(pán)的時(shí)機(jī)
# appendfsync always dofsync after every write to the append only log . Slow, Safest appendfsync everysec fsync only one time every second. Compromise # appendfsync no don't fsync, just let the OS flush the data when it wants. FasterAOF 優(yōu)點(diǎn)
- 使用AOF 會(huì)讓你的Redis持久性性能更好: 你可以使用不同的fsync策略:無(wú)fsync,每秒fsync,每次寫(xiě)的時(shí)候fsync.使用默認(rèn)的每秒fsync策略,Redis的性能依然很好(fsync是由后臺(tái)線程進(jìn)行處理 的,主線程會(huì)盡力處理客戶端請(qǐng)求),一旦出現(xiàn)故障,你最多丟失1秒的數(shù)據(jù).
- AOF文件是一個(gè)只進(jìn)行追加的日志文件,所以不需要寫(xiě)入seek,即使由于某些原因(磁盤(pán)空間已滿,寫(xiě)的過(guò)程中宕機(jī)等等)未執(zhí)行完整的寫(xiě)入命令,你也也可使用redis-check-aof工具修復(fù)這些問(wèn)題.
- Redis 可以在 AOF 文件體積變得過(guò)大時(shí),自動(dòng)地在后臺(tái)對(duì) AOF 進(jìn)行優(yōu)化重寫(xiě),使得AOF文件的體積不至于過(guò)大, 重寫(xiě)后的新 AOF 文件包含了恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合(例如將多個(gè)incr命令優(yōu)化為一個(gè)set命令)。 整個(gè)重寫(xiě)操作是絕對(duì)安全的,因?yàn)?Redis 在創(chuàng)建新 AOF 文件的過(guò)程中,會(huì)繼續(xù)將命令追加到現(xiàn)有的 AOF 文件里面,即使重寫(xiě)過(guò)程中發(fā)生停機(jī),現(xiàn)有的 AOF 文件也不會(huì)丟失。 而一旦新 AOF 文件創(chuàng)建完畢,Redis 就會(huì)從舊 AOF 文件切換到新 AOF 文件,并開(kāi)始對(duì)新 AOF 文件進(jìn)行追加操作。
- AOF 文件有序地保存了對(duì)數(shù)據(jù)庫(kù)執(zhí)行的所有寫(xiě)入操作, 這些寫(xiě)入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內(nèi)容非常容易被人讀懂, 對(duì)文件進(jìn)行分析(parse)也很輕松。 導(dǎo)出(export) AOF 文件也非常簡(jiǎn)單: 舉個(gè)例子, 如果你不小心執(zhí)行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫(xiě), 那么只要停止服務(wù)器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重啟 Redis , 就可以將數(shù)據(jù)集恢復(fù)到 FLUSHALL 執(zhí)行之前的狀態(tài)。
AOF 缺點(diǎn)
- 對(duì)于相同的數(shù)據(jù)集來(lái)說(shuō),AOF 文件的體積通常要大于 RDB 文件的體積。
- 根據(jù)所使用的 fsync 策略,AOF 的速度可能會(huì)慢于 RDB 。 在一般情況下, 每秒 fsync 的性能依然非常高, 而關(guān)閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負(fù)荷之下也是如此。 不過(guò)在處理巨大的寫(xiě)入載入時(shí),RDB 可以提供更有保證的最大延遲時(shí)間(latency)
如何選擇使用哪種持久化方式?
? ? ? ?你也可以同時(shí)開(kāi)啟兩種持久化方式, 在這種情況下, 當(dāng)redis重啟的時(shí)候會(huì)優(yōu)先載入AOF文件來(lái)恢復(fù)原始的數(shù)據(jù),因?yàn)樵谕ǔG闆r下AOF文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集要完整.
? ? ? ?一般來(lái)說(shuō), 如果想達(dá)到足以媲美 PostgreSQL 的數(shù)據(jù)安全性, 你應(yīng)該同時(shí)使用兩種持久化功能。
? ? ? ?如果你非常關(guān)心你的數(shù)據(jù), 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失, 那么你可以只使用 RDB 持久化。
? ? ? ?有很多用戶都只使用 AOF 持久化, 但我們并不推薦這種方式: 因?yàn)槎〞r(shí)生成 RDB 快照(snapshot)非常便于進(jìn)行數(shù)據(jù)庫(kù)備份, 并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比 AOF 恢復(fù)的速度要快。
redis持久化官方文檔
3. 內(nèi)存優(yōu)化
3.1 虛擬內(nèi)存
- 就是暫時(shí)把不經(jīng)常訪問(wèn)的數(shù)據(jù)從內(nèi)存交換到磁盤(pán)中,從而騰出寶貴的內(nèi)存空間用于其他需要訪問(wèn)的數(shù)據(jù)。redis虛擬內(nèi)存官方中文文檔。(虛擬內(nèi)存功能在2.6版本后已經(jīng)去除,個(gè)人感覺(jué)是因?yàn)楝F(xiàn)在內(nèi)存不足有更好的方式(如集群),沒(méi)必要因此去損失最關(guān)鍵的性能)
3.2 設(shè)置maxmemory
? ? ? ?為了存儲(chǔ)用戶數(shù)據(jù),當(dāng)設(shè)置了maxmemory后Redis會(huì)分配幾乎和maxmemory一樣大的內(nèi)存(然而也有可能還會(huì)有其他方面的一些內(nèi)存分配).
? ? ? ?精確的值可以在配置文件中設(shè)置,或者在啟動(dòng)后通過(guò) CONFIG SET 命令設(shè)置(see Using memory as an LRU cache for more info). Redis內(nèi)存管理方面,你需要注意以下幾點(diǎn):
? ? ? ?當(dāng)某些緩存被刪除后Redis并不是總是立即將內(nèi)存歸還給操作系統(tǒng)。這并不是redis所特有的,而是函數(shù)malloc()的特性。例如你緩存了5G的數(shù)據(jù),然后刪除了2G數(shù)據(jù),從操作系統(tǒng)看,redis可能仍然占用了5G的內(nèi)存(這個(gè)內(nèi)存叫RSS,后面會(huì)用到這個(gè)概念),即使redis已經(jīng)明確聲明只使用了3G的空間。這是因?yàn)閞edis使用的底層內(nèi)存分配器不會(huì)這么簡(jiǎn)單的就把內(nèi)存歸還給操作系統(tǒng),可能是因?yàn)橐呀?jīng)刪除的key和沒(méi)有刪除的key在同一個(gè)頁(yè)面(page),這樣就不能把完整的一頁(yè)歸還給操作系統(tǒng).
? ? ? ?上面的一點(diǎn)意味著,你應(yīng)該基于你可能會(huì)用到的 最大內(nèi)存 來(lái)指定redis的最大內(nèi)存。如果你的程序時(shí)不時(shí)的需要10G內(nèi)存,即便在大多數(shù)情況是使用5G內(nèi)存,你也需要指定最大內(nèi)存為10G.
? ? ? ?內(nèi)存分配器是智能的,可以復(fù)用用戶已經(jīng)釋放的內(nèi)存。所以當(dāng)使用的內(nèi)存從5G降低到3G時(shí),你可以重新添加更多的key,而不需要再向操作系統(tǒng)申請(qǐng)內(nèi)存。分配器將復(fù)用之前已經(jīng)釋放的2G內(nèi)存.
? ? ? ?因?yàn)檫@些,當(dāng)redis的peak內(nèi)存非常高于平時(shí)的內(nèi)存使用時(shí),碎片所占可用內(nèi)存的比例就會(huì)波動(dòng)很大。當(dāng)前使用的內(nèi)存除以實(shí)際使用的物理內(nèi)存(RSS)就是fragmentation;因?yàn)镽SS就是peak memory,所以當(dāng)大部分key被釋放的時(shí)候,此時(shí)內(nèi)存的mem_used / RSS就比較高.
? ? ? ?如果 maxmemory 沒(méi)有設(shè)置,redis就會(huì)一直向OS申請(qǐng)內(nèi)存,直到OS的所有內(nèi)存都被使用完。所以通常建議設(shè)置上redis的內(nèi)存限制。或許你也想設(shè)置 maxmemory-policy 的值為 noeviction(在redis的某些老版本默認(rèn) 并 不是這樣)
? ? ? ?設(shè)置了maxmemory后,當(dāng)redis的內(nèi)存達(dá)到內(nèi)存限制后,再向redis發(fā)送寫(xiě)指令,會(huì)返回一個(gè)內(nèi)存耗盡的錯(cuò)誤。錯(cuò)誤通常會(huì)觸發(fā)一個(gè)應(yīng)用程序錯(cuò)誤,但是不會(huì)導(dǎo)致整臺(tái)機(jī)器宕掉.
3.3 盡可能使用散列表(hashes)
參考此網(wǎng)址
4. 用redis實(shí)現(xiàn)分布式鎖
分布式鎖特性:
不管使用什么中間件,有幾點(diǎn)是實(shí)現(xiàn)分布式鎖必須要考慮到的。
- 互斥:互斥好像是必須的,否則怎么叫鎖。
- 死鎖: 如果一個(gè)線程獲得鎖,然后掛了,并沒(méi)有釋放鎖,致使其他節(jié)點(diǎn)(線程)永遠(yuǎn)無(wú)法獲取鎖,這就是死鎖。分布式鎖必須做到避免死鎖。
- 性能: 高并發(fā)分布式系統(tǒng)中,線程互斥等待會(huì)成為性能瓶頸,需要好的中間件和實(shí)現(xiàn)來(lái)保證性能。
- 鎖特性:考慮到復(fù)雜的場(chǎng)景,分布式鎖不能只是加鎖,然后一直等待。最好實(shí)現(xiàn)如Java Lock的一些功能如:鎖判斷,超時(shí)設(shè)置,可重入性等。
4.1 單機(jī)Redis的分布式鎖
分布式鎖的實(shí)現(xiàn)有哪些?
- 數(shù)據(jù)庫(kù)
- Memcached(add命令)
- Redis(setnx ex命令)從零開(kāi)始理解redis實(shí)現(xiàn)分布式鎖
- Zookeeper(臨時(shí)節(jié)點(diǎn))
- 等等
4.2 集群環(huán)境下redis的分布式鎖
對(duì)于集群環(huán)境下的redis,redis官方提出了redlock的算法,但目前也有較成熟的方案有redission,redission簡(jiǎn)單使用,redission使用,redission_github相關(guān)文章很多.
總結(jié)
以上是生活随笔為你收集整理的redis-高级特性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: redis - 基础
- 下一篇: springboot项目在idea中的热