(三)Redi緩存配置,持久化,訂閱發佈,主從複製和緩存相關問題以及解決

注:筆記整理來源 B站UP主狂神說Java

Redis.conf詳解

啓動通過配置文件!
單位:
1k => 1000 bytes
#1kb => 1024 bytes
#1m => 1000000 bytes
1mb => 10241024 bytes
1g => 1000000000 bytes
1gb => 1024
1024*1024 bytes

#units are case insensitive so 1GB 1Gb 1gB are all the same.
1.配置文件,unit單位對大小寫不敏感

包含 就好比Spring的Import ,include
#include /path/to/local.conf
 include /path/to/other.conf

2.網絡配置

//綁定的IP
bind 127.0.0.1
//保護模式
 protected-mode yes
//端口號設置
port 6379

3.通用配置

//以守護進程的方式運行,默認是no,需要手動開啓爲yes
daemonize yes

//如果以後臺方式運行,就需要指定一個pid文件
pidfile /var/run/redis_6379.pid

//日誌

#Specify the server verbosity level.
 This can be one of:
#debug (a lot of information, useful for development/testing)
 verbose (many rarely useful info, but not a mess like the debug level)
#notice (moderately verbose, what you want in production probably) 生產環境
 warning (only very important / critical messages are logged)
loglevel notice
logfile ""  //日誌的文件位置名

//數據庫的數量

databases 16

//是否顯示logo

always-show-logo yes

4.快照
持久化,在規定的時間內,執行了多少次操作,則會持久化到文件 .rdb文件 .aof文件
redis是內存數據庫,如果沒有持久化,那麼數據斷電即失去

save 900 1    //如果900s內,至少有1個key進行修改,就進行持久化操作
save 300 10     //如果300s內,至少有10個key進行修改,就進行持久化操作
save 60 10000     //如果60s內,至少有10000個key進行修改,就進行持久化操作
以後會自定義這個進行測試!

//持久化出錯,是否繼續工作
 stop-writes-on-bgsave-error yes

//是否壓縮rdb文件,需要消耗cpu資源
rdbcompression yes

//保存rdb文件的時候,進行錯誤的校驗
rdbchecksum yes

//rdb文件保存的目錄
dir ./

5.REPLICATION複製(主從複製)

#replicaof <masterip> <masterport>
replicaof<127.0.0.1><6379>

6.SECURITY安全

可以設置redis的密碼,默認沒有密碼.
127.0.0.1:6379> config get requirepass   獲取redis密碼
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass "123" 設置redis密碼
OK
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123     使用密碼進行登錄
OK
127.0.0.1:6379> ping
PONG
設置完密碼需要重啓客戶端.

7.限制 CLIENTS客戶端

#maxclients 10000   最大連接數
#maxmemory <bytes>   最大內存設置
#maxmemory-policy noeviction   內存達到最大的處理策略
         1. volatile-lru :只對設置了過期時間的key進行LRU(默認值)
         2.allkeys-lru :刪除lru算法的key
         3.volatile-random :隨機刪除即將過期的key
         4.allkeys-random :隨機刪除
         5.volatile-ttl :刪除即將過期的
         6.noeviction : 永不過期,報錯

8.APPEND ONLY MODE. aof配置

appendonly no //默認不開啓aof模式(默認使用rdb方式持久化,大部分情況rdb夠用)

appendfilename "appendonly.aof"   文件名(rdb文件的是 .rdb)

#appendfsync always 每次修改,都會sync(消耗性能)
appendfsync everysec  每秒執行一次sync,可能會丟失這1s的數據
#appendfsync no   不執行同步,這時候操作系統自己同步數據,速度最快
具體在AOF持久化中解釋

Redis持久化

Redis是內存數據庫,如果不將內存的數據庫狀態保存到磁盤,一旦服務器退出,服務器的數據庫狀態也會消失.所以redis提供了持久化.

RDB(Redis DataBase)

在指定時間間隔內將內存中的數據集快照寫入磁盤,也就是Snapshot快照,恢復的時候將快照文件直接讀到內存中.
Redis會單獨創建(fork)一個子進程來進行持久化,會將數據先寫入到一個臨時文件,待持久化過程結束了,在用這個臨時文件替換上次持久化好的文件.主進程不需要進行任何的IO操作,就保證了極高的性能.
如果需要進行大規模數據的恢復,且對於數據恢復的完整性不是很敏感,那麼RDB方式比AOF方式更加高效.RDB的缺點是最後一次持久化後的數據可能會丟失(服務器斷線).默認使用RDB.
  rdb保存的文件就是 dump.rdb文件
在這裏插入圖片描述
有時候需要對dump.rdb文件進行備份!

測試:
save 60 5   60秒內保存5次,就會觸發rdb操作

RDB觸發機制:
1.save的規則滿足情況下,會自動觸發rdb規則
2.執行flushall命令,也會觸發rdb規則
3.退出redis,也會觸發rdb規則
備份就自動生成一個dump.rdb文件

如何恢復rdb文件
1.只需要將rdb文件放在redis啓動目錄(配置文件中配置的rdb目錄文件),redis啓動時會自動檢查dump.rdb,恢復其中的數據.
2.查看需要存在的位置

127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin"   //如果在這個目錄下存在dump.rdb文件,啓動時就會自動掃描,恢復數據

優缺點
優點:
1.適合大規模數據的恢復!
2.如果對數據完整性要求不高!可以使用
缺點:
1.需要一定的時間間隔!redis如果意外宕機,這個最後一次修改數據就沒了!
2.fork進程會佔用內存空間!

AOF(Append Only File)

AOF: 將所有執行的命令都記錄下來,history,恢復的時候就把這個文件內容全部在執行一遍.

以日誌的形式來記錄每個寫操作,將redis執行過的所有指令記錄下來(讀操作不記錄),只需追加文件,不可以改寫文件,
redis啓動之初會將文件的全部命令執行一遍來構建數據,就是redis重啓的話就根據日誌文件的內容將寫指令執行一次以
完成數據的恢復工作.
AOF保存的文件: appendfilename “appendonly.aof”
在這裏插入圖片描述
appendonly no //默認不開啓,需要手動設置爲yes

appendsync always 每次都修改
appendsync everysec 每秒修改
appendsync no 不修改

使用AOF的時候,只需要將appendonly 的值設置爲yes 即可.
如果aof文件有錯誤,redis是啓動不起來的!需要修復aof文件: redis-check-aof --fix 文件

優點和缺點
優點:
1.每一次修改都同步,文件的完整性會更好!
2.每秒同步一次,可能會丟失一秒的數據!
3.從不同步:效率最高!

缺點:
1.相對於數據文件來說(內存佔用高),aof遠遠大於rdb,恢復的速度也比rdb慢
2.aof運行效率比rdb慢,所以redis默認爲rdb.

擴展:

1.RDB持久化方式能夠在指定的時間間隔內對內存的數據進行存儲快照
2.AOF持久化操作記錄每次對服務器寫的操作,當服務器重啓的時候會重新執行這些命令來恢復原始的數據,AOF命令以Redis協議追加保存每次寫的操作到文件末尾,Redis還能對AOF文件進行後臺重寫,使AOF文件的體積不至於過大.
3.只做緩存,如果只希望數據在服務器運行的時候存在,可以不用持久化 4.同時開啓兩種持久化方式
-在這種情況下,當redis重啓的時候會優先載入AOF文件來恢復原始的數據,因爲在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整.
-RDB的數據不實時,同時使用兩者時重啓服務器也只會去找AOF文件,那要不要只使用AOF呢?不!  因爲RDB更適合於備份數據庫(AOF在不斷變化不好備份),快速重啓,而且也不會有AOF可能潛在的Bug.
5.性能建議
-因爲RDB文件只用做備用,建議在Slave上持久化RDB文件,而且只要15分鐘備份一次即可,只保留save 900 1(15分鐘 1次操作就備份)這條規則
-如果是Enable AOF,好處是在最惡劣情況下也只會丟失不超過兩秒的數據,啓動時只需要load自己的AOF文件.代價一:帶來了持續的IO
代價二:AOF rewrite的最後將rewrite過程中產生的新數據寫到新文件造成的阻塞幾乎是不可避免的.只要硬盤許可,應儘量減少AOF rewrite的頻率,AOF重寫的基礎大小默認爲64M,太小,可以設爲5G以上.
-如果不Enable AOF,緊靠Master-Slave Repllcation實現高可用性也可以,能節省一大筆IO,也減少了rewrite時帶來的系統波動.代價是如果Master-slave同時宕機,會丟失十幾分鐘的數據,啓動時也要比較兩個Master/Slave中的RDB文件,載入較新的那個,微博就是這種架構.

Redis實現訂閱發佈

Redis發佈訂閱(pub/sub) 是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息.(微博,微信)
Redis客戶端可以訂閱任意數量的頻道.
訂閱/發佈消息圖:

第一個角色:消息發送者 二:公共頻道 三:消息訂閱者

下圖展示了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關係:
在這裏插入圖片描述
當有新消息通過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被髮送給訂閱它的三個客戶端:
在這裏插入圖片描述

Redis 發佈訂閱命令

下表列出了 redis 發佈訂閱常用命令:

1 PSUBSCRIBE pattern [pattern …] 訂閱一個或多個符合給定模式的頻道。
2 PUBSUB subcommand [argument [argument …]] 查看訂閱與發佈系統狀態。
3 PUBLISH channel message 將信息發送到指定的頻道。
4 PUNSUBSCRIBE [pattern [pattern …]] 退訂所有給定模式的頻道。
5 SUBSCRIBE channel [channel …] 訂閱給定的一個或多個頻道的信息。
6 UNSUBSCRIBE [channel [channel …]] 指退訂給定的頻道。

案例:
訂閱端:

redis 127.0.0.1:6379> SUBSCRIBE redisChat   訂閱一個頻道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
//等待消息的推送
1) "message"  //消息
2) "redisChat"     //頻道
3) "Redis is a great caching technique" //內容
1) "message"
2) "redisChat"
3) "Learn redis by runoob.com"

發佈端:

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"
(integer) 1
redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"
(integer) 1

Redis發佈訂閱使用場景:
1.實時消息系統!
2.實時聊天(頻道當做聊天室,將信息回寫給所有人)
3.訂閱,關注系統!
稍微複雜的場景: 消息中間件

Redis主從複製

主從複製是指將一臺Redis服務器的數據,複製到其他Redis服務器.前者稱爲主節點(master/leader),後者稱爲從節點(slave/follower);數據的複製是單向的,只能由主節點到從節點.Master以寫爲主,Slave以讀爲主.

默認情況下,每臺Redis服務器都是主節點,且一個主節點可以有多個從節點(或者沒有),但一個從節點只能有一個主節點.

主從複製的作用包括:
1.數據冗餘:主從複製實現了數據的熱備份,是持久化之外的一種數據冗餘方式.
2.故障恢復:當主節點出現問題,可以由從節點提供服務,實現快速的故障恢復,是一種服務的冗餘
3.負載均衡:在主從輔助的基礎上,配合讀寫分離,可以由主節點提供寫服務,從節點提供讀服務,分擔服務器負載,可以提高服務器併發量.
4.高可用基石:主從複製還是哨兵和集羣能夠實現的基礎,因此說主從複製是redis高可用的基礎.

一般而言,將Redis運用項目工程中,一臺Redis是萬萬不能的(會宕機)
1.從結構:單個Redis服務器會發生單點故障,並且一臺服務器需要處理的請求負載,壓力較大
2.從容量:單個Redis服務器內存容量有限,就算一臺Redis服務器內存容量爲256G,也不能將所有內存用作Redis存儲內存.(一般單臺Redis最大使用內存不超過20G)
一般對數據的操作都是讀多寫少,所以採用主從複製(一主(主服務器用來寫)二從(從服務器用來讀))

環境配置:
只配置從庫,不用配置主庫!(Redis默認就是主庫)

查看當前庫的信息: info replication

#Replication
role:master   角色 master
connected_slave:0   連接的從機
master_replid:   
master_replid2:
master_repl_offset:0
master_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

複製三個redis.conf ,從服務器配置文件需要修改:port ,pidfile ,logfile, dump.rdb文件!

一主(6379)二從(6380,6381):
從機1配置:

127.0.0.1:6380> slaveof host(127.0.0.1)   port(6379)
127.0.0.1:6380> info replication
#Replication role:slave master_host:127.0.0.1 master_port:6379
.....

從機2配置:

127.0.0.1:6381> slaveof host(127.0.0.1)   port(6379)
127.0.0.1:6381> info replication
#Replication
role:slave
master_host:127.0.0.1
master_port:6379
.....

真實的主從配置應該在配置文件中配置,這樣的話就是永久的.

#replicaof <masterip> <masterport>
replicaof<127.0.0.1><6379>

細節:

主機可以寫,從機不可以寫,只能讀! 主機中的所有信息和數據都會被從機保存

測試:主機斷開連接,從機依舊連接到主機,但是沒有寫操作了(主機down機),如果主機回來了,從機依舊可以獲取到主機寫的東西.(高可用性)

如果使用命令行配置的從機,這時候從機斷開連接,從機就會變回主機!只要再次變爲從機,數據立馬可以得到!
複製原理:
Slave啓動成功連接到master後會發送一個sync命令,Master接到命令,啓動後臺的存盤進程,同時收集所有接收到的用於修改數據集命令,在後臺進程執行完畢後,master將傳送整個數據文件到slave,並完成一次完全同步!
-全量複製:
而Slave服務在接收到數據庫文件數據後,將其存盤並加載到內存中.
-增值複製:
Master繼續將新的所收集到的修改命令依次傳給slave,完成同步,但是隻要是重新連接master,一次完全同步(全量複製)將被自動執行.

Slaveof no one:將從機設置爲主機
如果主機斷開了連接,可以用Slaveof no one 命令讓自己變成主機!這個時候之前斷開的主機恢復了,只能重新配置,設置從機.

Redis哨兵模式(公司所有的集羣都用哨兵模式)

在主從中自動選舉主機.
主從切換技術的方法:當主服務器宕機後,需要手動將從服務器轉換爲主服務器,人工干預,費時費力,還會造成一段時間內服務不可用. 所以就出現了哨兵模式!
哨兵模式:能夠後臺監控主機是否故障,如果故障了根據投票數自動將從機設置爲主機!
  是一種特殊的模式,Redis提供了哨兵的命令,哨兵是一個獨立的進程.
原理:哨兵通過發送命令,等待Redis服務器響應,從而監控運行的多個Redis實例!
在這裏插入圖片描述
在這裏插入圖片描述

假設主服務器宕機,哨兵1先檢測到,系統並不會進行failover過程,僅僅是哨兵1主觀認爲主服務器下線,當後面的哨兵也檢測到主服務器不可用,並且數量達到一定時,哨兵就會進行一次投票,投票的結果由一個哨兵發起,進行failover故障轉移操作.切換成功,就會通過發佈訂閱模式,讓各個哨兵把自己監控的從服務器切換主機,這個過程稱爲客觀下線.

測試:
1.配置哨兵配置文件 sentinel.conf

  #sentinel monitor 被監控的名稱  IP地址  端口號  1(數字代表如果主機掛了,slave投票看誰接替成爲主機)

sentinel monitor myredis 127.0.0.1 6379
2.啓動哨兵!

   redis-sentinel config/sentinel.conf

當主機宕機之後,哨兵會投票選出新主機,當原先主機重新連接,此時原先的主機就會在哨兵模式的操作下,變爲新主機的從機!!

哨兵模式的全部配置:
基礎配置:

protected-mode no       #關閉保護模式                                                                                                 
port 26479                    #端口                                                                                           
daemonize yes             #使用後臺模式啓動                                                                                               
pidfile "/var/run/redis-sentinel_26479.pid"                       #進程id文件                                                       
logfile "/usr/local/redis/sentinel/sentinel_26479.log"           #日誌文件                                                        
dir "/usr/local/redis/sentinel"               #工作目錄

核心配置:

sentinel monitor <master-name> <ip> <redis-port> <quorum> 
告訴sentinel去監聽地址爲ip:port的一個master,這裏的master-name可以自定義,quorum是一個數字,指明當有多少個sentinel認爲一個master失效時,master纔算真正失效

sentinel auth-pass <master-name> <password>
 設置連接master和slave時的密碼,注意的是sentinel不能分別爲master和slave設置不同的密碼,因此master和slave的密碼應該設置相同。
 
sentinel down-after-milliseconds <master-name> <milliseconds> 
這個配置項指定了需要多少失效時間,一個master纔會被這個sentinel主觀地認爲是不可用的。 單位是毫秒,默認爲30秒 

sentinel parallel-syncs <master-name> <numslaves> 
 這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行 同步,這個數字越小,完成failover所需的時間就越長,但是如果這個數字越大,就意味着越 多的slave因爲replication而不可用。可以通過將這個值設爲 1 來保證每次只有一個slave 處於不能處理命令請求的狀態。 
 
sentinel failover-timeout <master-name> <milliseconds> failover-timeout 可以用在以下這些方面:     
	1. 同一個sentinel對同一個master兩次failover之間的間隔時間。  
	2. 當一個slave從一個錯誤的master那裏同步數據開始計算時間。直到slave被糾正爲向正確的master那裏同步數據時。   
	3.當想要取消一個正在進行的failover所需要的時間。   
	4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個超時,slaves依然會被正確配置爲指向master,但是就不按parallel-syncs所配置的規則來了。

優點:
1.哨兵集羣,基於主從複製模式,所有的主從配置優點全有
2.主從可以切換,故障可以轉移,系統的可用性增強
3.哨兵模式就是主從模式的升級,手動到自動,更加健壯!

缺點:
1.Redis不好在線擴容,集羣容量一旦達到上限,在線擴容就十分複雜!
2.實現哨兵模式的配置是很麻煩的!裏面有很多選擇!

緩存穿透及解決方案(本身應在緩存中查詢,但查不到數據,緩存被穿透,最後全部到數據庫查詢)

緩存穿透:key對應的數據在數據源並不存在,每次針對此key的請求從緩存獲取不到,請求都會到數據源,從而可能壓垮數據源。比如用一個不存在的用戶id獲取用戶信息,不論緩存還是數據庫都沒有,若黑客利用此漏洞進行攻擊可能壓垮數據庫。
解決:
方案一:採用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
方案二:更爲簡單粗暴的方法。如果一個查詢返回的數據爲空(不管是數據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
存在的問題:
1.如果空值能夠被緩存起來,這就意味着緩存需要更多的空間存儲更多的鍵,因爲當中有很多空值的鍵.
2.即使對空值設置了過期時間,還是會存在緩存層和儲存層的數據有一段時間窗口的不一致,這對於需要保證一致性的業務有影響.

緩存擊穿及解決方案(量太大,緩存過期!)

緩存擊穿:key對應的數據存在,但在redis中過期,(key失效的瞬間)此時若有大量併發請求過來,這些請求發現緩存過期一般都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。

解決:
1.設置熱點數據永不過期.
2.加互斥鎖:使用分佈式鎖,保證對於每個key同時只能有一個線程去查詢後端服務,其他線程沒有獲得鎖的權限,需要等待.這種方式將高併發的壓力轉移到了分佈式鎖,因此對分佈式鎖的考驗很大.

緩存雪崩及解決方案 (一個地方崩全局崩)

緩存雪崩:當緩存服務器重啓或者大量緩存集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(比如DB)帶來很大壓力。 Redis宕機

解決方案:
1.Redis高可用:既然Redis可能會掛掉,那多設幾臺Redis,一臺掛了,其他幾臺還可以工作.(異地多活)
2.限流降級:在緩存失效後,通過加鎖或者阻塞隊列來控制讀數據庫寫緩存的線程數量,比如對某個key只允許一個線程查詢數據和寫緩存,其他線程進行等待.
3.數據預熱:在正式部署之前,先把可能用到的數據先訪問一遍,這樣部分數據就會加載到緩存中,在即將發生大併發訪問前手動觸發加載緩存不同的key,設置不同的過期時間,讓緩存失效的時間點儘量均勻.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章