本文使用的是redis5.0.7版本
一、主從複製
單個Redis如果因爲某種原因宕機的話,可能會導致Redis服務不可用,可以使用主從複製實現一主多從,主節點負責寫的操作,從節點負責讀的操作,主節點會定期將數據同步到從節點中,保證數據一致性的問題。
1.配置
##在需在從(一或多個)節點redis.conf文件中配置以下
slaveof 192.168.75.128 6379 ##主節點ip和端口
masterauth 123456 ## 主節點密碼
2.主從複製數據同步的過程
1.Redis從節點向主節點建立socket連接
2.Redis採用全量或者增量的形式將數據同步給從節點
從Redis2.8版本以後 過程採用增量和全量同步
全量複製:一般用於在初次的複製場景(從節點與主節點一次建立)
增量複製:網絡出現問題,從節點再次連接主節點時,主節點補發缺少的數據,每次數據增量同步
3.缺陷
若主節點宕機,將會導致整個redis環境不可進行寫操作,需要人爲更改主操作。
解決方案:使用哨兵機制實現Redis集羣主從選舉策略
二、Redis哨兵機制
Redis的哨兵機制是爲了解決以上的主從複製的缺點(選舉問題),解決問題保證我們的Redis高可用,實現自動化故障發現與故障轉移。
1.原理
哨兵機制每個10s時間只需要配置監聽我們的主節點就可以獲取當前整個Redis集羣的環境列表,採用info 命令形式。
哨兵不建議是單機的,最好每個Redis節點都需要配置哨兵監聽。
哨兵集羣原理是如何:多個哨兵都執行同一個主的master節點,訂閱到相同都通道,有新的哨兵加入都會向通道中發送自己服務的信息,該通道的訂閱者可以發現新哨兵的加入,隨後相互建立長連接。
Master的故障發現 單個哨兵會向主的master節點發送ping的命令,如果master節點沒有及時的響應,哨兵會認爲該master節點爲“主觀不可用狀態”會發送給其他都哨兵確認該Master節點是否不可用,當前確認的哨兵節點數>=quorum(可配置),會實現重新選舉。
2.實現
## 將redis源文件的sentinel.conf,copy到你redis的目錄
vi sentinel.conf
##配置主機信息 和選舉同意人數
sentinel monitor mymaster 192.168.75.128 6379 2
##master的密碼
sentinel auth-pass mymaster 123456
##sentinel心跳檢測主3秒內無響應,視爲掛掉,開始切換其他從爲主
sentinel down-after-milliseconds mymaster 3000
##每次最多可以有1個從同步主。一個從同步結束,另一個從開始同步。
sentinel parallel-syncs mymaster 1
##主從切換超時時間
sentinel failover-timeout mymaster 18000
##啓動哨兵
./redis-sentinel ./sentinel.conf
##其他 檢查哨兵狀態
redis-cli -h 192.168.31.187 -p 5000
sentinel master mymaster
SENTINEL slaves mymaster
SENTINEL sentinels mymaster
SENTINEL get-master-addr-by-name mymaster
三、Redis安全控制
1.緩存穿透
產生的背景:
緩存穿透是指使用不存在的key進行大量的高併發查詢,導致緩存無法命中,每次請求都要都要穿透到後端數據庫查詢,使得數據庫的壓力非常大,甚至導致數據庫服務壓死;
(高併發下,redis中不存在key,每次都要請求數據庫,導致數據庫服務器壓力大)
解決方案:
接口層實現api限流、用戶授權、id檢查等;
從緩存和數據庫都取不到數據的話,一樣將數據庫空值放入緩存中,設置30s有效期避免使用同一個id對數據庫攻擊壓力大;
2.緩存擊穿
產生背景:
在高併發的情況下,當一個緩存key過期時,因爲訪問該key請求較大,多個請求同時發現緩存過期,因此對多個請求同時數據庫查詢、同時向Redis寫入緩存數據,這樣會導致數據庫的壓力非常大;
(高併發下,key過期,多個請求同時發現過期,同時請求數據庫,同時寫入緩存,導致數據庫服務器壓力大)
解決方案:
- 使用分佈式鎖
保證在分佈式情況下,使用分佈式鎖保證對於每個key同時只允許只有一個線程查詢到後端服務,其他沒有獲取到鎖的權限,只需要等待即可;這種高併發壓力直接轉移到分佈式鎖上,對分佈式鎖的壓力非常大。
- 使用本地鎖
使用本地鎖與分佈式鎖機制一樣,只不過分佈式鎖適應於服務集羣、本地鎖僅限於單個服務使用。
- 軟過過期
設置熱點數據永不過期或者異步延長過期時間;
- 布隆過濾器
3.緩存雪崩
緩存雪崩指緩存服務器重啓或者大量的緩存集中在某個時間段失效,突然給數據庫產生了巨大的壓力,甚至擊垮數據庫的情況。(大量key同時失效) 解決思路:對不用的數據使用不同的失效時間,加上隨機數
四、Redis Cluster集羣
1.傳統Redis集羣存在那些問題
Redis哨兵集羣模式,每個節點都保存全量同步數據,冗餘的數據比較多;而在Redis Cluster模式中集羣中採用分片集羣模式,可以減少冗餘數據,缺點就是構建該集羣模式成本非常高。
2.傳統RedisCluster集羣的原理
Redis3.0開始官方推出了集羣模式 RedisCluster,原理採用hash槽的概念,預先分配16384個卡槽,並且將該卡槽分配給具體服務的節點;通過key進行crc16(key)%16384 獲取餘數,餘數就是對應的卡槽的位置,一個卡槽可以存放多個不同的key,從而將讀或者寫轉發到該卡槽的服務的節點。 最大的優點:動態擴容、縮容。
3.RedisCluster集羣模式環境搭建
mkdir rediscluster
cd rediscluster/
mkdir redis7000
mkdir redis7001
mkdir redis7002
mkdir redis7003
mkdir redis7004
mkdir redis7005
##每個配置文件內容
daemonize yes #後臺啓動
protected-mode no ; ## 允許外部訪問
port 7005 #修改端口號,從7000到7005
cluster-enabled yes #開啓cluster,去掉註釋
cluster-config-file 7000nodes.conf #自動生成
cluster-node-timeout 15000 #節點通信時間
logfile "/usr/local/redis/bin/rediscluster/redis7000/redis.log" #日誌
dbfilename dump7000.rdb #RDB文件
##啓動我們的redis
./redis-server ./rediscluster/redis7000/redis.conf
./redis-server ./rediscluster/redis7001/redis.conf
./redis-server ./rediscluster/redis7002/redis.conf
./redis-server ./rediscluster/redis7003/redis.conf
./redis-server ./rediscluster/redis7004/redis.conf
./redis-server ./rediscluster/redis7005/redis.conf
##連接一個redis
./redis-cli -h 192.168.75.128 -p 7000
> set karma karma
(error) CLUSTERDOWN Hash slot not served ##說明沒有分配hash槽
##分配卡槽
> ./redis-cli --cluster create 192.168.75.128:7000 192.168.75.128:7001 192.168.75.128:7002 192.168.75.128:7003 192.168.75.128:7004 192.168.75.128:7005 --cluster-replicas 1 (建議最好使用服務器的ip地址搭建)
> ./redis-cli -h 192.168.75.128 -p 7000
> set karma karma
(error MOVED 16365 192.168.75.128:7002)
## 添加-c 可自動跳轉到該key存儲的分片
> ./redis-cli -h 192.168.75.128 -p 7000 –c
> set karma karma
Redirected to slot [11740] located at 192.168.75.128:7002
OK
> ./redis-cli --cluster help
4.RedisCluster集羣模式擴容縮容節點
> ./redis-server ./rediscluster/redis7006/redis.conf
> ./redis-server ./rediscluster/redis7007/redis.conf
> ./redis-cli -h 192.168.75.128 -p 7000
##Redis擴容
## 新增一個主節點 爲7006
> ./redis-cli --cluster add-node 192.168.75.128:7006 192.168.75.128:7000
## 新增一個從節點 爲7007
> ./redis-cli --cluster add-node 192.168.75.128:7007 192.168.75.128:7000 --cluster-slave --cluster-master-id 6889d6165709872a2e71d5bde6ee6630b6172c91
## 新增的7006 是沒有任何槽位
## 分配Redis槽位擴容
> cluster slots
> ./redis-cli --cluster reshard 192.168.75.128:7006
How many slots do you want to move (from 1 to 16384)? 4096 ##移動多少卡槽? 16384/4 = 4096
What is the receiving node ID? ## 接受id是多少? cluster nodes查看7006的id
Source node #1: all ## 是否重新分片的源節點 所有
Do you want to proceed with the proposed reshard plan (yes/no)? yes
## 查看7006卡槽連接信息
> ./redis-cli --cluster check 192.168.75.128:7006
##Redis縮容 與分配Redis槽位擴容相反
> ./redis-cli --cluster reshard 192.168.75.128:7000
## 略
> ./redis-cli --cluster del-node 192.168.75.128:7003 1a05262bb8d6918fb4382d9bf764e2b607e4092e ##要刪除的節點及id