redis高可用、redis叢集、redis快取優化
阿新 • • 發佈:2022-05-23
今日內容概要
- redis高可用
- redis叢集
- redis快取優化
內容詳細
1、redis高可用
# 主從複製存在的問題: 1 主從複製,主節點發生故障,需要做故障轉移,可以手動轉移:讓其中一個slave變成master--->哨兵 2 主從複製,只能主寫資料,所以寫能力和儲存能力有限----》叢集 # 案例 -一主兩從,主寫資料,從讀資料 -如果主庫掛掉,從庫只能讀,redis就不能對外提供服務了,它就不高可用 -即便主掛掉,選一個從庫作為主庫,繼續對外提供服務 就是高可用 -原來的主庫,又啟動起來了,它現在作為從庫 # 使用哨兵完成上面的事情 sentinel--》哨兵 ##### 搭建步驟 # 搭建一主兩從 # 配置3個哨兵 # 主一 daemonize yes dir ./data3 protected-mode no bind 0.0.0.0 logfile "redis_sentinel3.log" sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 # 從一 port 26380 daemonize yes dir ./data2 protected-mode no bind 0.0.0.0 logfile "redis_sentinel3.log" sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 # 從二 port 26381 daemonize yes dir ./data protected-mode no bind 0.0.0.0 logfile "redis_sentinel1.log" sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 # 啟動三個哨兵 ./src/redis-sentinel sentinel_26379.conf ./src/redis-sentinel sentinel_26378.conf ./src/redis-sentinel sentinel_26377.conf # 客戶端連線到某一個redis上 info # 檢視主從資訊 # 客戶端連到某個 sentinel上(一個sentinel類似於一個redis-server,客戶端可以連線) redis-cli -p 26379 # 連到這個哨兵上 info ''' # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3 ''' # 演示故障切換 # 停掉主庫---》6379 shutdown # 哨兵認為主掛了,會自動選一個從庫當主庫 info 選擇了6380作為主了 # 把6379啟動,6379現在變成從庫
哨兵搭建後的python連線
# python連線redis---》寫寫到主庫,讀從從庫中讀---》一旦用了高可用(主庫會變)---》python連線哨兵---》通過哨兵返回主,去寫,返回從,去讀 import redis from redis.sentinel import Sentinel # 連線哨兵伺服器(主機名也可以用域名) # 127.0.0.1:26379 sentinel = Sentinel([('127.0.0.1', 26379), ('127.0.0.1', 26380), ('127.0.0.1', 26381) ], socket_timeout=5) print(sentinel) # 獲取主伺服器地址 master = sentinel.discover_master('mymaster') print(master) # 返回所有主 # 獲取從伺服器地址 slave = sentinel.discover_slaves('mymaster') print(slave) # 返回所有從 ##### 讀寫分離 # 獲取主伺服器進行寫入 master = sentinel.master_for('mymaster', socket_timeout=0.5) w_ret = master.set('foo', 'bar') slave = sentinel.slave_for('mymaster', socket_timeout=0.5) r_ret = slave.get('foo') print(r_ret)
2、redis叢集
# 主從複製,只能主寫資料,所以寫能力和儲存能力有限----》叢集 # 存在問題 1 併發量:單機redis qps為10w/s,但是我們可能需要百萬級別的併發量 2 資料量:機器記憶體16g--256g,如果存500g資料呢? # 解決:加機器,分散式 redis cluster 在2015年的 3.0 版本加入了,滿足分散式的需求 # 分散式資料庫 假設全量的資料非常大,500g,單機已經無法滿足,我們需要進行分割槽,分到若干個子集中 # 分割槽方式 -雜湊分佈 原理:hash分割槽: 節點取餘 ,假設3臺機器, hash(key)%3,落到不同節點上 優點:熱點資料分散 缺點:不利於批量查詢 -順序分佈 原理:100個數據分到3個節點上 1--33第一個節點;34--66第二個節點;67--100第三個節點(很多關係型資料庫使用此種方式,mysql通常用它) 缺點:熱點資料太集中 # mysql 官方沒有叢集方案---》第三方解決方案---》順序,雜湊 # 雜湊分割槽 -節點取餘:後期擴容--》遷移資料總量大---》推薦翻倍庫容 -一致性 hash 每個節點負責一部分資料,對key進行hash,得到結果在node1和node2之間,就放到node2中,順時針查詢 擴容遷移資料遷移少,資料不均衡 -虛擬槽分割槽(redis叢集) 預設虛擬槽:每個槽對映一個數據子集,一般比節點數大 良好的雜湊函式:如CRC16 服務端管理節點、槽、資料:如redis cluster(槽的範圍0–16383)
2.1 搭建
# 6臺機器,3個節點的叢集,另外三臺做副本庫(從庫)
# 自動故障轉移,3個主節點,如果有一個掛了,另外一個從庫就會升級為主庫
# redis的埠7000
# redis的埠7001
# redis的埠7002
# redis的埠7003
# redis的埠7004
# redis的埠7005
# 只要叢集中有一個故障了,整個就不對外提供服務了,這個實際不合理,假設有50個節點,一個節點故障了,所有不提供服務了
# 配置檔案
port 7000
daemonize yes
dir "/root/s20/redis-5.0.7/data"
logfile "7000.log"
dbfilename "dump-7000.rdb"
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-require-full-coverage yes
# 快速生成其他配置
sed 's/7000/7001/g' redis-7000.conf > redis-7001.conf
sed 's/7000/7002/g' redis-7000.conf > redis-7002.conf
sed 's/7000/7003/g' redis-7000.conf > redis-7003.conf
sed 's/7000/7004/g' redis-7000.conf > redis-7004.conf
sed 's/7000/7005/g' redis-7000.conf > redis-7005.conf
# 啟動6個節點
./src/redis-server ./redis-7000.conf
ps -ef |grep redis
./src/redis-server ./redis-7001.conf
./src/redis-server ./redis-7002.conf
./src/redis-server ./redis-7003.conf
./src/redis-server ./redis-7004.conf
./src/redis-server ./redis-7005.conf
### 客戶端連上---》放資料--->想搭建叢集---》叢集模式沒有分槽---》放的這個資料不知道放到哪個節點--》放不進去----》搭建完成才能寫入資料
## 客戶端連結上的命令:
cluster nodes # 如果沒有搭建完成,只能看到自己
cluster info # 叢集狀態是成功\失敗的
# 搭建叢集 4.x以前版本,比較麻煩
-先meet
-指派槽
-建立主從
# 快速搭建叢集 4.x以後,只需要這一條,自動meet,自動指派槽,自動建主從
# 注意這個數字 cluster-replicas 1 ---》指的是每個主節點有幾個從節點
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
### 演示寫入資料
-在7001上寫入 name lqz
-去7002上查不到name
-對name crc16雜湊運算完---》算完的槽--->知道哪個節點管了哪些槽---》告訴你去哪個節點存
# 以叢集模式登陸,
-無論在哪個主節點,都能寫入資料,獲取資料
redis-cli -c -p 埠 # 以叢集模式登陸,如果操作不到,自動重定向過去
# 演示故障轉移
-7001 是個主庫---》主庫停掉--》7005從庫會自動升級為主庫
2.2 叢集擴容/縮容
## 叢集擴容
sed 's/7000/7006/g' redis-7000.conf > redis-7006.conf
sed 's/7000/7007/g' redis-7000.conf > redis-7007.conf
./src/redis-server ./redis-7006.conf
./src/redis-server ./redis-7007.conf
### 方式一
在7000上執行
redis-cli -p 7000 cluster meet 127.0.0.1 7006
redis-cli -p 7000 cluster meet 127.0.0.1 7007
### 方式二
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000
# 讓7007做為7006的從
redis-cli -p 7007 cluster replicate 2d657119470fd7c65c366698f20cc104295b7555
##### 分槽
redis-cli --cluster reshard 127.0.0.1:7000
# 16384總共平均分配到4個節點,每個節點需要有:4096槽
數4096 指定到7006節點上
自動從三個節點中的每個節點拿一部分槽放到7006身上,湊夠4096個
###### 縮容
# 下線遷槽(把7006的1366個槽遷移到7000上)--->把槽遷走
# 從誰那裡遷到誰身上
redis-cli --cluster reshard --cluster-from 2d657119470fd7c65c366698f20cc104295b7555 --cluster-to 997257c78c2995372c8cde228850b4b101d2a03b --cluster-slots 1365 127.0.0.1:7000
yes
redis-cli --cluster reshard --cluster-from 2d657119470fd7c65c366698f20cc104295b7555 --cluster-to c763786ad7fa9c65fb9182a8cfe0be4825ee96a0 --cluster-slots 1366 127.0.0.1:7005
yes
redis-cli --cluster reshard --cluster-from 2d657119470fd7c65c366698f20cc104295b7555 --cluster-to 1993efb87276df5986bdca56930aaa8ec3e78287 --cluster-slots 1366 127.0.0.1:7002
yes
# 忘記節點,關閉節點
redis-cli --cluster del-node 127.0.0.1:7000 1cddf0889d525516ad38a714ad5d38bead74dbcb(從庫id) # 先下從,再下主,因為先下主會觸發故障轉移
redis-cli --cluster del-node 127.0.0.1:7000 2d657119470fd7c65c366698f20cc104295b7555(主庫id)
# 關掉其中一個主,另一個從立馬變成主頂上, 重啟停止的主,發現變成了從
3、redis快取優化
# 雙寫一致性
-定時更新
-增資料刪快取
-增資料改快取
# redis自身有快取更新策略---》redis佔記憶體不能無限大,可以控制,記憶體就是滿了
# 快取更新策略
1. LRU -Least Recently Used,沒有被使用時間最長的
# LRU配置
maxmemory-policy:volatile-lru
(1)noeviction: 如果記憶體使用達到了maxmemory,client還要繼續寫入資料,那麼就直接報錯給客戶端
(2)allkeys-lru: 就是我們常說的LRU演算法,移除掉最近最少使用的那些keys對應的資料,ps最長用的策略
(3)volatile-lru: 也是採取LRU演算法,但是僅僅針對那些設定了指定存活時間(TTL)的key才會清理掉
(4)allkeys-random: 隨機選擇一些key來刪除掉
(5)volatile-random: 隨機選擇一些設定了TTL的key來刪除掉
(6)volatile-ttl: 移除掉部分keys,選擇那些TTL時間比較短的keys
2. LFU -Least Frequenty User,一定時間段內使用次數最少的
# LFU配置 Redis4.0之後為maxmemory_policy淘汰策略添加了兩個LFU模式:
volatile-lfu:對有過期時間的key採用LFU淘汰演算法
allkeys-lfu:對全部key採用LFU淘汰演算法
# 還有2個配置可以調整LFU演算法:
lfu-log-factor 10
lfu-decay-time 1
# lfu-log-factor可以調整計數器counter的增長速度,lfu-log-factor越大,counter增長的越慢。
# lfu-decay-time是一個以分鐘為單位的數值,可以調整counter的減少速度
3. FIFO -First In First Out
### 快取穿透--(快取中沒有,資料中也沒有---》基本是惡意攻擊)
# 描述:
快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷髮起請求,如發起為id為“-1”的資料或id為特別大不存在的資料。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大
# 解決方案:
1 介面層增加校驗,如使用者鑑權校驗,id做基礎校驗,id<=0的直接攔截
2 從快取取不到的資料,在資料庫中也沒有取到,這時也可以將key-value對寫為key-null,快取有效時間可以設定短點,如30秒(設定太長會導致正常情況也沒法使用)。這樣可以防止攻擊使用者反覆用同一個id暴力攻擊
3 通過布隆過濾器實現---》把資料庫中存在的資料,放到布隆過濾器中--》查的時候,去布隆過濾器查一下在不在---》在的話,繼續往後走,不在的話直接給前端錯誤
### 快取擊穿(快取中沒有,資料庫中有)
# 描述:
快取擊穿是指快取中沒有但資料庫中有的資料(一般是快取時間到期),這時由於併發使用者特別多,同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力
# 解決方案:
設定熱點資料永遠不過期。
### 快取雪崩
# 描述:
快取雪崩是指快取中資料大批量到過期時間,而查詢資料量巨大,引起資料庫壓力過大甚至down機。和快取擊穿不同的是,快取擊穿指併發查同一條資料,快取雪崩是不同資料都過期了,很多資料都查不到從而查資料庫
# 解決方案:
1 快取資料的過期時間設定隨機,防止同一時間大量資料過期現象發生。
2 如果快取資料庫是分散式部署,將熱點資料均勻分佈在不同搞得快取資料庫中
3 設定熱點資料永遠不過期。