第六章 Redis

6.1 Redis基礎 6.2 Redis持久化 6.3 Redis相關問題 6.4 Redis各種集羣方案

6.1 Redis基礎

爲什麼Redis快?(本機10萬 QPS,經網絡IO 3萬QPS)

1 Redis基於內存
2 數據結構簡單,對數據操作也簡單的非關係型數據庫(類似hash)
3 單線程處理,所以都是線程安全。也可以開啓多個redis多線程執行
4 使用I/O多路複用模型,非阻塞IO(具體所有IO模型在Netty篇寫,這裏一帶而過)

爲什麼Redis是單線程?

因爲Redis瓶頸基於內存而不是CPU,所以Redis沒有必要使用多線程

Redis具體應用

1 String類型

常用操作 set, get, incr,位操作等
應用
	最基本的數據類型,保存各種信息等,這裏重點寫二進制下使用場景。
	二進制下bitmap只有byte概念,不會處理數據,顯示長度以byte長度顯示。

	簡單的二進制操作 
	setbit k1 9 1(繼承k1之前值,把k1的第九個bit設爲1)
	BITCOUNT k1 0 2(k1下0到2中3個字節有幾個1)
	
	比如統計用戶窗口登陸次數。
	setbit k1 22 1(設置k1用戶在第22天登陸一次,然後用bitcount數)
	
	setbit 20200101 7
	setbit 20200101 20
	則表示2020年1月1號,7號和20號用戶登陸了

2 List類型

常用操作 lpush, lrange等,
因爲可以左右推拉 可以用於存儲商鋪商品

3 Hash類型

常用操作 hmset,hget,hset等

4 Set類型

常用操作sadd,smembers
可以用於推薦系統,共同好友交集

5 Sorted Set類型(按分值排序然後按照分母)

常用操作zadd zrangebyscore
用於排行榜,評論分頁

6 HyperLogLog

一般用於存儲地理位置Geo,每個key佔空間很小

6.2 Redis持久化

快照(RDB)

特定時間的全量數據,加載快,容易丟失數據。

爲什麼RDB加載快,容易丟失數據?

因爲比如數據999999999,在日誌中佔9個字節。但是快照下用bit存只佔4個字節。
進行了字節壓縮,所以二進制恢復速度快,但是bit也造成容易丟失

RDB文件配置

save 900 1
rdbcompression yes //開啓壓縮字節後才緩存
stop-writes-on-bgsave-error yes //可以開啓bgsave

save:阻塞redis服務進程直到RDB被創建完畢
bgsave:fork出一個子進程來創建RDB,不阻塞服務器進程

日誌(AOF)

傾向實時,記錄完整,每個操作追加日誌文件。
加載慢,有冗餘,會拉低redis整體性能

AOF如何處理冗餘?

通過bg rewrite aof指令進行數據重寫整合,刪除重複寫入的操作

AOF如何具體重寫處理冗餘步驟?

1 主進程fork()出子進程
2 子進程把新的AOF文件寫到臨時文件,不依賴原來的主進程。
3 期間主進程會持續把新的變動寫入內存和原來老AOF日誌
4 主進程得到子進程重寫AOF信號,也會往新AOF中添加
5 新AOF重寫完畢,替換老AOF

Redis的選擇

redis4.x版本之前 默認使用RDB快照,人工開啓日誌時,快照會失效。

redis4.x版本之後 使用AOF混合模式。
快照bgsave做不實時的全量持久化,日誌做近期指令的增量持久化

6.3 Redis相關問題

Redis內存壓縮–縮減鍵值對象等

Redis的Sorted Set底層實現是跳錶

Redis的過期處理

主動處理(每秒10次)
	1 從相關過期祕鑰中(設置過過期時間並且已經過期的key)隨機測試20個
	2 刪除所有已經過期的key
	3 如果大於百分之25的測試key都已經過期,則重複步驟1

被動處理
	訪問key時,檢查這個key是否過期,如果過期則刪除

RDB快照:過期的key不會持久化到快照中
AOF日誌:遇到過期的key會追加一個DEL命令到日誌文件中

回收策略

可在配置文件中設置內存回收策略,比如
LRU刪除最遠使用的key
LFU刪除使用頻率最小的key

海量數據key裏查詢某固定前綴key

使用 scan指令

Redis分佈式鎖

1 使用setnx鎖
setnx有嚴重問題,在setnx拿到鎖後,設置expire過期時間前,程序掛了,
鎖就永遠不會釋放

2 使用紅鎖
紅鎖原理
 	順序向所有節點請求加鎖
	根據一定的超時時間來推斷是不是跳過該節點
 	一半以上節點加鎖成功並且花費時間小於鎖的有效期
 	認定加鎖成功

使用Redis做簡單消息隊列

redis提供發佈和訂閱功能
缺點:消息發佈無狀態,無法保證消息可達

Redis管道批量處理

可以減少redis每次連接時間。1000次hset會執行1000次連接和1000次執行時間。
用管道,每個管道執行100次。1000次hset會執行10次連接和1000次執行時間。

Reids 4大經典緩存問題

1 緩存穿透

發生場景:當redis和數據庫都沒有這個請求的數據

方案1:緩存空對象
當redis和mysql都沒有數據時候,給當前key加一個空value緩存。
缺點:太佔空間

方案2:布隆過濾器(空間小,有誤判率,底層bit數組)
1 使用谷歌提供的布隆過濾器
缺點:位數組 int最大長度21億有限制且只能單機用於JVM內存

2 使用redis提供的布隆過濾器
由string二進制運算,最大長度42億,第三方可以redis內存,可以分佈式集羣
缺點:redis自己維護,開發者無法刪除

2 緩存擊穿

發生場景:redis沒有數據,但是數據庫有數據。
上一秒緩存剛好過期,下一秒大量併發相同查詢擊穿數據庫

方案步驟
1 當1000個相同執行併發查詢redis
2 添加redis鎖,一個redis查並且加緩存如果mysql有數據,999個阻塞
3 再查詢redis
4 查詢mysql

3 雪崩

發生場景:redis大量數據同時丟失

方案
高可用集羣,過期時間錯開

4 redis和mysql如何保證數據一致性

方案1:延遲雙刪
	rm_redis
	update_db
	sleep xxx ms
	rm_redis
方案2:串行化隊列,異步處理
	使redis必須一個一個處理,保證每次處理數據都一定正確

6.4 Redis各種集羣方案

想畫圖,圖片一直上傳不了,CSDN的程序員好倒閉了

AKF劃分原理

x軸 redis橫向主備全量同步
y軸 業務劃分拆解 拆分秒殺系統,商品詳情頁等等
z軸 商品詳情頁同業務分治
		商品詳情頁1-10000數據一個
		10001-20000數據一個
		等等拆分

	拆分方式
	1 客戶端實現
	2 代理實現
	3 集羣技術
	4 根據路由算法克服代理瓶頸

併發很大情況下

1 單點故障(全量同步主備)
	命令行,配置文件,哨兵實現主從
2 性能瓶頸,壓力大
	分片集羣,分而治之

主從同步

1 命令行執行
		shaveof [ip] [port]
2 配置文件配置
		redis.conf中配置 
		slaveof [ip] [port] 
		slave-read-only yes
3 哨兵實現主從

主從複製流程(異步複製)

從服務端通過psync命令發送主從已有的同步進度(同步源ID,同步進度offset)

如果同步源ID一樣,master沒變動。則通過offset增量同步到從節點

如果同步源ID不一樣,master換了,則全量同步。刪除舊數據,
主節點生成快照傳到從節點,加載到從內存

哨兵實現主從(官方推薦1主2從,3哨兵)

哨兵機制分爲三層

1 主從數據庫層
2 哨兵集羣層
3 客戶端

2-3層面通訊
當配置完哨兵後,客戶端通過SENTINEL get-master-addr-by-name mymaster
指令,通過哨兵拿到數據。客戶端只會和哨兵集羣層交流,不再和數據庫層面交流。	
								
1-2層面通訊
哨兵保存主庫信息,通過ping和主從數據層保持通訊。哨兵內部也集羣,哨兵集體監控主從數據庫
層每一個數據庫,哨兵集體確認主從數據庫保持通訊纔算做主從數據庫仍然存活。

哨兵配置文件 sentinel.conf

sentinel monitor mymaster [IP] [Port] 2 
mymaster [IP] [Port]爲監控對象
2位 2個及以上哨兵認爲死亡纔算死亡

哨兵相關問題

哨兵如何拿到主從數據庫層面信息?

哨兵conf文件保存主庫信息,通過info命令,主從信息自動發現。

什麼是主觀下線?

哨兵ping未收到相應,會主觀自身認爲該數據庫下線了

什麼是客觀下線?

達到配置數量的哨兵ping未迴應,集體成功認爲該數據庫下線了

哨兵起初領導選舉算法

raft算法,隨機延遲拉票投出主從。
如果沒有被拉過票則投票給他

中間主掛了,從中選主方案

1 看優先級
2 看數據同步情況
3 最小的run id

最終主從切換過程

1 即將變主 自動slaveof配置爲no one
2 從節點自動配置 slaveof [master ip] [master port]

網絡分區可能導致腦裂(網絡分區產生多個主從)

解決方案
1 設置master最少從數量
2 設置從選主最大延遲時間
3 如果違背1,2,則主拒絕寫請求

Redis分片集羣

1 Redis Sharding集羣

原理:一致性哈希
(很重要,相關文章很多,百度搜搜吧,相關問題不難,略)

2 Redis Cluster集羣

官方建議集羣1000個實例,雖然理論可以16384個實例

3.0版本後實現自動分片,貌似比Sharding好?不清楚,作爲一個萌新不多評論。

原理:hash值%16384,使用哈希槽slot

實例啓動

redis-cli工具創建集羣
redis-cli -- cluster -create ip1:port1 ip2:port2 .... --cluster -replicas 1
replicas表示設置多少個副本,假設我們配置6個redis,replicas設爲1
那麼則會自動配置成3主,3從

--cluster reshard 可以修改server區間段
--cluster check 可以檢查集羣信息

集羣之間如何通訊?

每個節點有TCP端口與其他節點TCP端口連接,檢測和故障轉移和哨兵類似

ask和move重定向區別

1 如果redis不屬於當前節點,redis返回moved
2 如果當前redis節點正處理slot槽遷移,則代表此處key暫時不在這裏,返回ask,
告訴客戶端請求重定向

對集羣任何信息發佈信息,都會在整個集羣內部傳播

數據傾斜問題

前期規劃+後期reshard,slot槽也有自動rebalance

reshard區間段,setslot遷移slot

在這個集羣中,默認從節點處理讀,所有寫請求會重定向到主節點
也可以設置節點的可讀,可寫狀態

主從之間存在數據不一致問題

監控問題

monitor命令,會下降百分之50性能,實時監控redis操作
info命令,會顯示redis相關信息
也有相關redis監控軟件下載
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章