1、爲什麼使用redis
(一)性能
我們在碰到需要執行耗時特別久,且結果不頻繁變動的SQL,就特別適合將運行結果放入緩存。
這樣,後面的請求就去緩存中讀取,使得請求能夠迅速響應。
(二)併發
在大併發的情況下,所有的請求直接訪問數據庫,數據庫會出現連接異常。
這個時候,就需要使用redis做一個緩衝操作,讓請求先訪問到redis,而不是直接訪問數據庫。
2、單線程的redis爲什麼這麼快
redis是單線程工作模型:
(一) 純內存操作
(二) 單線程操作,避免了頻繁的上下文切換
(三) 採用了非阻塞I/O多路複用機制
3、redis的數據類型,以及每種數據類型的使用場景
(一) String
這個其實沒啥好說的,最常規的set/get操作,value可以是String也可以是數字。一般做一些複雜的計數功能的緩存。
(二) hash
這裏value存放的是結構化的對象,比較方便的就是操作其中的某個字段。博主在做單點登錄的時候,就是用這種數據結構存儲用戶信息,以cookieId作爲key,設置30分鐘爲緩存過期時間,能很好的模擬出類似session的效果。
(三) list
使用List的數據結構,可以做簡單的消息隊列的功能。另外還有一個就是,可以利用lrange命令,做基於redis的分頁功能,性能極佳,用戶體驗好。本人還用一個場景,很合適---取行情信息。就也是個生產者和消費者的場景。LIST可以很好的完成排隊,先進先出的原則。
(四) set
因爲set堆放的是一堆不重複值的集合。所以可以做全局去重的功能。爲什麼不用JVM自帶的Set進行去重?因爲我們的系統一般都是集羣部署,使用JVM自帶的Set,比較麻煩,難道爲了一個做一個全局去重,再起一個公共服務,太麻煩了。
另外,就是利用交集、並集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。
(五) sorted set
sorted set多了一個權重參數score,集合中的元素能夠按score進行排列。可以做排行榜應用,取TOP N操作。
4、redis的過期策略以及內存淘汰機制
redis採用的是 定期刪除+惰性刪除策略。
爲什麼不用定時刪除策略?
定時刪除,用一個定時器來負責監視key,過期則自動刪除。雖然內存及時釋放,但是十分消耗CPU資源。
在大併發請求下,CPU要將時間應用在處理請求,而不是刪除key,因此沒有采用這一策略.
定期刪除,redis默認每隔100ms檢查,是否有過期的key,有過期key則刪除。需要說明的是,redis不是每個100ms將所有的key檢查一次,而是隨機抽取進行檢查(如果每隔100ms,全部key進行檢查,redis豈不是卡死)。
於是,惰性刪除派上用場。也就是說在你獲取某個key的時候,redis會檢查一下這個key是否過期了?如果過期了此時就會刪除。
如果定期刪除沒刪除key。然後也沒有即時去請求key,也就是說惰性刪除也沒生效。這樣,redis的內存會越來越高。那麼就應該採用內存淘汰機制。
在 redis.conf 中有一行配置
# maxmemory-policy volatile-lru
該配置就是配內存淘汰策略的。
1)noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯。
2)allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key。推薦使用
3)allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。
4)volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key。這種情況一般是把redis既當緩存,又做持久化存儲的時候才用。不推薦 // TODO 爲什麼不用這個???
5)volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key。依然不推薦
6)volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除。不推薦
ps:如果沒有設置 expire 的key, 不滿足先決條件(prerequisites); 那麼 volatile-lru, volatile-random 和 volatile-ttl 策略的行爲, 和 noeviction(不刪除) 基本上一致。
6、redis和數據庫雙寫一致性問題
數據庫和緩存雙寫,就必然會存在不一致的問題。如果對數據有強一致性要求,不能放緩存。我們所做的一切,只能保證最終一致性。另外,我們所做的方案其實從根本上來說,只能說降低不一致發生的概率,無法完全避免。因此,有強一致性要求的數據,不能放緩存。
首先,採取正確更新策略:先更新數據庫,再刪緩存。其次,因爲可能存在刪除緩存失敗的問題,提供一個補償措施即可,例如利用消息隊列。
Redis中數據存儲模式有兩種:cache-only以及persistence
cache-only: 只作爲"緩存"服務,不提供數據的持久化操作,數據在服務停止後消失,因此在此模式下也不存在數據恢復的問題,該模式的優點是效率高,容易擴展,缺點是安全性較低。
persistence:該模式下將內存中的數據持久化到磁盤文件,服務重啓後數據可以恢復,優點是相對安全。
對於persistence持久化存儲,Redis提供了兩種方式:
Redis Database 簡稱(RDB) 以及 Append-only file 簡稱(AOF)
RDB
RDB是在某個時間點將數據寫入一個臨時文件,持久化結束後,用這個臨時文件替換上次持久化的文件,達到數據恢復。
優點:使用單獨子進程來進行持久化,主進程不會進行任何IO操作,保證了redis的高性能
缺點:RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失。所以這種方式更適合數據要求不嚴謹的時候
執行數據寫入到臨時文件的時間點是可以通過配置來自己確定的,通過配置redis在n秒內如果超過m個key被修改就執行一次RDB操作。這個操作就類似於在這個時間點來保存一次Redis的所有數據,一次快照數據。所有這個持久化方法也通常叫做 snapshots。
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進行持久化存儲;
save 900 1
# save時間: 更改了10個key300s進行存儲;
save 300 10
# save時間: 更改10000個key60s進行存儲。
save 60 10000
## 當snapshot時出現錯誤無法繼續時,是否阻塞客戶端“變更操作”,“錯誤”可能因爲磁盤已滿/磁盤故障/OS級別異常等
stop-writes-on-bgsave-error yes
## 是否啓用rdb文件壓縮,默認爲“yes”,壓縮往往意味着“額外的cpu消耗”,同時也意味這較小的文件尺寸以及較短的網絡傳輸時間
rdbcompression yes
snapshot 觸發的時機,是有“間隔時間”和“變更次數”共同決定,同時符合2個條件纔會觸發snapshot, 否則“變更次數”會被繼續累加到下一個“間隔時間”上。snapshot過程中並不阻塞客戶端請求。snapshot首先將數據寫入臨時文件,當成功結束後,將臨時文件重名爲dump.rdb。
使用RDB恢復數據:自動的持久化數據存儲到dump.rdb後。實際只要重啓redis服務即可完成(啓動redis的server時會從dump.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和RDB各有優缺點,這是有它們各自的特點所決定:
1) AOF更加安全,可以將數據更加及時的同步到文件中,但是AOF需要較多的磁盤IO開支,AOF文件尺寸較大,文件內容恢復數度相對較慢。
2) snapshot安全性較差,它是“正常時期”數據備份以及master-slave數據同步的最佳手段,文件尺寸較小,恢復數度較快。
可以通過配置文件來指定它們中的一種,或者同時使用它們(不建議同時使用),或者全部禁用
在架構良好的環境中,master 通常使用 AOF,slave 使用 snapshot,主要原因是
master需要首先確保數據完整性,它作爲數據備份的第一選擇;
slave提供只讀服務(目前slave只能提供讀取服務),它的主要目的就是快速響應客戶端read請求;
但是如果你的redis運行在網絡穩定性差/物理環境糟糕情況下,建議你master和slave均採取AOF,這個在master和slave角色切換時,可以減少“人工數據備份”/“人工引導數據恢復”的時間成本;
如果你的環境一切非常良好,且服務需要接收密集性的write操作,那麼建議master採取snapshot,而slave採用AOF。