Redis的使用分兩點:
性能
如下圖所示,我們在碰到需要執行耗時特別久,且結果不頻繁變動的SQL,就特別適合將運行結果放入緩存。這樣,后面的請求就去緩存中讀取,使得請求能夠迅速響應。
並發
在大並發的情況下,所有的請求直接訪問數據庫,數據庫會出現連接異常。這個時候,就需要使用redis做一個緩沖操作,讓請求先訪問到redis,而不是直接訪問數據庫
使用redis有什么缺點
分析:大家用redis這么久,這個問題是必須要了解的,基本上使用redis都會碰到一些問題,常見的也就幾個。
回答:主要是四個問題
(一)緩存和數據庫雙寫一致性問題
(二)緩存雪崩問題
(三)緩存擊穿問題
(四)緩存的並發競爭問題
redis的過期策略以及內存淘汰機制
分析:這個問題其實相當重要,到底redis有沒有用到家,這個問題就可以看出來。比如你的redis只能存儲5G數據,課時你寫了10G,那會刪除5G的數據。怎么刪的,則會個問題思考過嗎?還有,你的數據已經設置了過期時間了,內存占有率還是比較高,有思考過嗎?且看我來講解:
redis是采用定期刪除+惰性刪除策略
為什么不用定時刪除策略?:
定時刪除,用一個定時器來負責監視key,當這個key過期就自動刪除,雖然內存及時釋放,但是十分消耗CPU資源,在大並發請求下CPU要盡可能的把時間都用在處理請求,而不是刪除key,因此沒有采用這一策略
定期刪除+惰性刪除是如何工作的呢?
定時刪除,redis默認每100ms檢查是否有過期的key,有過期的key則刪除。需要說明的是redis不是每個100ms將所有的key檢查一次,而是隨機抽取進行檢查(如果每100ms,全部key進行檢查,redis豈不是卡死了)。因此,如果只采用定期策略,會導致很多key到時間沒有刪除
也就是使用定時刪除會導致刪除不完全,於是惰性刪除就登場了。
也就是說你在獲取key的時候,redis會檢查一下,這個key如果設置過期時間那么是否過期了?如果過期 此時就刪除。
采用定期刪除+惰性刪除就沒問題了呢?
不是的如果定期刪除沒有刪除key,然后你也沒有及時去請求這個key,也就是說惰性刪除也沒有生效。這樣redis的內存會越來越高,那么就應該采用內存淘汰機制。
在redis.conf中有一行配置
# maxmemory-policy volatile-lru
該配置就是配內存淘汰策略的(什么,你沒配過?好好反省一下自己)
1)noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯。應該沒人用吧。
2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key。推薦使用,目前項目在用這種。
3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。應該也沒人用吧,你不刪最少使用Key,去隨機刪。
4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key。這種情況一般是把redis既當緩存,又做持久化存儲的時候才用。不推薦
5)volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key。依然不推薦
6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除。不推薦
ps:如果沒有設置 expire 的key, 不滿足先決條件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行為, 和 noeviction(不刪除) 基本上一致。
Redis持久化原理及配置詳解
Redis的強大功能很大程度上是由於其將所有數據都存儲在內存中。為了使Redis在重啟后仍能保證數據不丟失,需要將數據從內存中以某種形式持久化到硬盤中。Redis支持兩種持久化方式,一種是RDB方式,一種是AOF方式。可以單獨使用其中一種或兩種結合使用。(持久化即將數據保存到磁盤,機器宕機或者重啟數據不丟失,存儲到內存中的數據會丟失)
Redis有兩種持久化的方式:快照(RDB
文件)和追加式文件(AOF
文件):
- RDB持久化方式會在一個特定的間隔保存那個時間點的一個數據快照。
- AOF持久化方式則會記錄每一個服務器收到的寫操作。在服務啟動時,這些記錄的操作會逐條執行從而重建出原來的數據。寫操作命令記錄的格式跟Redis協議一致,以追加的方式進行保存。
- Redis的持久化是可以禁用的,就是說你可以讓數據的生命周期只存在於服務器的運行時間里。
- 兩種方式的持久化是可以同時存在的,但是當Redis重啟時,AOF文件會被優先用於重建數據。
RDB概述:
RDB是在某個時間點將數據寫入一個臨時文件,持久化結束后,用這個臨時文件替換上次持久化的文件,達到數據恢復。
優點:使用單獨子進程來進行持久化,主進程不會進行任何IO操作,保證了redis的高性能
缺點:RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失。所以這種方式更適合數據要求不嚴謹的時候
RDB是Redis默認的持久化方式,所以RDB是默認開啟的
redis.conf中的具體配置參數如下;
#dbfilename:持久化數據存儲在本地的文件 dbfilename dump.rdb #dir:持久化數據存儲在本地的路徑,如果是在/redis/redis-3.0.6/src下啟動的redis-cli,則數據會存儲在當前src目錄下 dir ./ ##snapshot觸發的時機,save <seconds> <changes> ##如下為900秒后,至少有一個變更操作,才會snapshot ##對於此值的設置,需要謹慎,評估系統的變更操作密集程度 ##可以通過“save “””來關閉snapshot功能 #save時間,以下分別表示更改了1個key時間隔900s進行持久化存儲;更改了10個key300s進行存儲;更改10000個key60s進行存儲。 save 900 1 save 300 10 save 60 10000 ##當snapshot時出現錯誤無法繼續時,是否阻塞客戶端“變更操作”,“錯誤”可能因為磁盤已滿/磁盤故障/OS級別異常等 stop-writes-on-bgsave-error yes ##是否啟用rdb文件壓縮,默認為“yes”,壓縮往往意味着“額外的cpu消耗”,同時也意味這較小的文件尺寸以及較短的網絡傳輸時間 rdbcompression yes
人們常說的redis的默認持久化就是因為它默認支持RDB模式,又因為RDB支持持久化所以就說redis默認持久化,但是我們寫的內容又無法滿足這個持久化的條件所以就沒有把數據存儲起來
禁用redis快照:
如果想禁用快照保存的功能,可以通過注釋掉所有"save"配置達到,或者在最后一條"save"配置后添加如下的配置:
save ""
快照並不是很可靠。如果你的電腦突然宕機了,或者電源斷了,又或者不小心殺掉了進程,那么最新的數據就會丟失。而AOF文件則提供了一種更為可靠的持久化方式。每當Redis接受到會修改數據集的命令時,就會把命令追加到AOF文件里,當你重啟Redis時,AOF里的命令會被重新執行一次,重建數據。
AOF概述
Redis的AOF持久化策略是將發送到Redis服務端的每一條命令都記錄下來,並且保存在硬盤的AOF文件中。可以通過參數appendonly來設置是否啟用AOF。AOF文件的位置和RDB的位置相同,都是通過dir參數設置,默認的文件名是appendonly.aof,可以通過appendfilename參數修改。
將“操作 + 數據”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已經寫入到文件或者即將寫入),才進行實際的數據變更當server需要數據恢復時,可以直接replay此日志文件,即可還原所有的操作過程。AOF相對可靠
優點:
- 比RDB可靠。你可以制定不同的fsync策略:不進行fsync、每秒fsync一次和每次查詢進行fsync。默認是每秒fsync一次。這意味着你最多丟失一秒鍾的數據。
- AOF日志文件是一個純追加的文件。就算是遇到突然停電的情況,也不會出現日志的定位或者損壞問題。甚至如果因為某些原因(例如磁盤滿了)命令只寫了一半到日志文件里,我們也可以用
redis-check-aof
這個工具很簡單的進行修復。 - 當AOF文件太大時,Redis會自動在后台進行重寫。重寫很安全,因為重寫是在一個新的文件上進行,同時Redis會繼續往舊的文件追加數據。新文件上會寫入能重建當前數據集的最小操作命令的集合。當新文件重寫完,Redis會把新舊文件進行切換,然后開始把數據寫到新文件上。
- AOF把操作命令以簡單易懂的格式一條接一條的保存在文件里,很容易導出來用於恢復數據。例如我們不小心用
FLUSHALL
命令把所有數據刷掉了,只要文件沒有被重寫,我們可以把服務停掉,把最后那條命令刪掉,然后重啟服務,這樣就能把被刷掉的數據恢復回來。
缺點:
- 在相同的數據集下,AOF文件的大小一般會比RDB文件大。
- 在某些fsync策略下,AOF的速度會比RDB慢。通常fsync設置為每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達到RDB的水平。
AOF默認關閉,開啟方法,修改配置文件reds.conf:appendonly yes
##此選項為aof功能的開關,默認為“no”,可以通過“yes”來開啟aof功能 ##只有在“yes”下,aof重寫/文件同步等特性才會生效 appendonly yes ##指定aof文件名稱 appendfilename appendonly.aof ##指定aof操作中文件同步策略,有三個合法值:always everysec no,默認為everysec appendfsync everysec ##在aof-rewrite期間,appendfsync是否暫緩文件同步,"no"表示“不暫緩”,“yes”表示“暫緩”,默認為“no” no-appendfsync-on-rewrite no ##aof文件rewrite觸發的最小文件尺寸(mb,gb),只有大於此aof文件大於此尺寸是才會觸發rewrite,默認“64mb”,建議“512mb” auto-aof-rewrite-min-size 64mb ##相對於“上一次”rewrite,本次rewrite觸發時aof文件應該增長的百分比。 ##每一次rewrite之后,redis都會記錄下此時“新aof”文件的大小(例如A),那么當aof文件增長到A*(1 + p)之后 ##觸發下一次rewrite,每一次aof記錄的添加,都會檢測當前aof文件的尺寸。 auto-aof-rewrite-percentage 100
AOF是文件操作,對於變更操作比較密集的server,那么必將造成磁盤IO的負荷加重;此外linux對文件操作采取了“延遲寫入”手段,即並非每次write操作都會觸發實際磁盤操作,而是進入了buffer中,當buffer數據達到閥值時觸發實際寫入(也有其他時機),這是linux對文件系統的優化,但是這卻有可能帶來隱患,如果buffer沒有刷新到磁盤,此時物理機器失效(比如斷電),那么有可能導致最后一條或者多條aof記錄的丟失。通過上述配置文件,可以得知redis提供了3中aof記錄同步選項:
always:每一條aof記錄都立即同步到文件,這是最安全的方式,也以為更多的磁盤操作和阻塞延遲,是IO開支較大。
everysec:每秒同步一次,性能和安全都比較中庸的方式,也是redis推薦的方式。如果遇到物理服務器故障,有可能導致最近一秒內aof記錄丟失(可能為部分丟失)。
no:redis並不直接調用文件同步,而是交給操作系統來處理,操作系統可以根據buffer填充情況/通道空閑時間等擇機觸發同步;這是一種普通的文件操作方式。性能較好,在物理服務器故障時,數據丟失量會因OS配置有關。
其實,我們可以選擇的太少,everysec是最佳的選擇。如果你非常在意每個數據都極其可靠,建議你選擇一款“關系性數據庫”吧。
主從:
通過持久化功能,Redis保證了即使在服務器重啟的情況下也不會損失(或少量損失)數據,因為持久化會把內存中數據保存到硬盤上,重啟會從硬盤上加載數據。
。但是由於數據是存儲在一台服務器上的,如果這台服務器出現硬盤故障等問題,也會導致數據丟失。為了避免單點故障,通常的做法是將數據庫復制多個副本以部署在不同的服務器上,這樣即使有一台服務器出現故障,其他服務器依然可以繼續提供服務。為此, Redis 提供了復制(replication)功能,可以實現當一台數據庫中的數據更新后,自動將更新的數據同步到其他數據庫上。
概述
1、redis的復制功能是支持多個數據庫之間的數據同步。一類是主數據庫(master)一類是從數據庫(slave),主數據庫可以進行讀寫操作,當發生寫操作的時候自動將數據同步到從數據庫,而從數據庫一般是只讀的,並接收主數據庫同步過來的數據,一個主數據庫可以有多個從數據庫,而一個從數據庫只能有一個主數據庫。
2、通過redis的復制功能可以很好的實現數據庫的讀寫分離,提高服務器的負載能力。主數據庫主要進行寫操作,而從數據庫負責讀操作
主從復制過程:
過程:
1:當一個從數據庫啟動時,會向主數據庫發送sync命令,
2:主數據庫接收到sync命令后會開始在后台保存快照(執行rdb操作),並將保存期間接收到的命令緩存起來
3:當快照完成后,redis會將快照文件和所有緩存的命令發送給從數據庫。
4:從數據庫收到后,會載入快照文件並執行收到的緩存的命令。
主從復制是樂觀復制,當客戶端發送寫執行給主,主執行完立即將結果返回客戶端,並異步的把命令發送給從,從而不影響性能。也可以設置至少同步給多少個從主才可寫。 無硬盤復制:如果硬盤效率低將會影響復制性能,2.8之后可以設置無硬盤復制,repl-diskless-sync yes
哨兵:
當主數據庫遇到異常中斷服務后,開發者可以通過手動的方式選擇一個從數據庫來升格為主數據庫,以使得系統能夠繼續提供服務。
然而整個過程相對麻煩且需要人工介入,難以實現自動化。 為此,Redis 2.6中提供了哨兵2.8才穩定,哨兵工具來實現自動化的系統監控和故障恢復功能。 哨兵的作用就是監控redis主、從數據庫是否正常運行,主出現故障自動將從數據庫轉換為主數據庫。
顧名思義,哨兵的作用就是監控Redis系統的運行狀況。它的功能包括以下兩個。
(1)監控主數據庫和從數據庫是否正常運行。
(2)主數據庫出現故障時自動將從數據庫轉換為主數據庫。
哨兵就是為了監測你的主數據庫是否出問題,如果主數據庫出問題就會把從數據庫升為主數據庫,也可以設置多個哨兵來監測主從,然后多個哨兵監測的時候就會運用投票來監測主從,
如果是主數據庫掛掉 ,就需要你的這些多個哨兵來投票 當多票當選的時候就會讓從數據庫變成主,當有哨兵機制的時候是進行連接哨兵 ,哨兵再連接數據庫