redis的八大特性
速度快、持久化、多種數據結構、支持多種編輯語言,功能豐富、簡單、主從複製、高可用和分佈式
速度快
10萬 QPS
內存操作
C語言編寫
單線程,一個時刻只能執行一條命令
多路IO複用模型
數據結構
string hash list set zset
BitMaps:位圖
HyperLogLog:超小內存唯一值計數
GEO:地理信息定位
功能豐富
發佈訂閱
Lua腳本
事務
pipeline(可以統一執行查詢的命令)
redis典型應用場景
緩存系統、計數器、消息隊列系統、排行榜、社交網絡
redis常用配置
# daemonize
是否是守護進程(no|yes),默認是no,建議yes
# port
redis對外端口號
# logfile
redis系統日誌
# dir
redis工作目錄
redis的命令
通用命令
keys:查詢所有的key
dbsize:key的數量
exists key 判斷key是否存在
del key [key...]
expire key seconds
type key
string
set get del
incr key # key自增1,如果key不存在,自增後get(key) = 1
decr key # key自減1,如果key不存在,自增後get(key) = -1
incrby key k # key自增1,如果key不存在,自增後get(key) = k
decrby key k # key自減1,如果key不存在,自增後get(key) = -k
# 應用場景:計數器
set key value # 不管key是否存在,都設置
setnx key value # key不存在,才設置
set key value xx # key存在,才設置
慢查詢
1.默認值
config get slowlog-max-len = 128
config get slowlog-log-slower-than = 1000
2.修改配置文件重啓
3.動態配置
config set slow-max-len 1000
config set slowlog-log-slower-than 1000
# 慢查詢指令
1.slowlog get [n]:獲取慢查詢隊列
2.slowlog len:獲取慢查詢隊列長度
3.slowlog reset:清空慢查詢隊列
# 運維校驗
1.slowlog-max-len不要設置過大,默認10ms,通常設置1ms
2.slowlog-log-slower-than不要設置過小,通常設置1000左右
3.理解命令生命週期
4.定期持久化慢查詢
生命週期
pipline
# 流水線
pipline把n個命令打包起來,傳輸到服務端(只需要傳輸一次),服務端按順序執行命令,然後把結果打包起來依次返回
# 兩點注意
1.redis的命令時間是微秒級別的
2.pipline每次條數要控制(網絡)
# 使用建議
1.注意每次pipline攜帶數據量
2.pipline每次只能作用在一個redis節點上
3.M操作與pipline區別
發佈訂閱
# 發佈者(publisher)
# 頻道(channel)
# 訂閱者(subscriber)
# API
publish
subscribe
unsubscribe
其他
Bitmap
把字符串的每個字母轉成二進制了
set name zs
getbit name 0 # 獲取索引0上的值,
setbit name 1 1 # 設置索引爲1上的值爲1,只能設爲0或1
# 使用經驗
1.type=string,最大512MB
2.注意setbit時的偏移量,可能有較大耗時
3.位圖不是絕對好
HyperLogLog
1.基於HyperLogLog算法:極小空間完成獨立數量統計
2.本質還是字符串
# 三個命令
1.pfadd key element [element...]:向HyperLogLog添加元素,裏面的元素都是唯一的
2.pfcount key [key...]:計算HyperLogLog的獨立總數
3.pfmerge destkey sourcekey [sourcekey ...]:合併多個HyperLogLog
# 使用場景,統計總數
# 缺點:有錯誤率,官方給的是0.81%
GEO
GEO(地理信息定位):存儲經緯度,計算兩地距離,範圍計算等
# 添加城市的經緯度
geoadd key longitude latitude member
# 例如
geoadd cities:locations 116.28 39.22 beijing # 存儲北京的經緯度
geoadd cities:locations 117.12 39.08 tianjin
# 取出城市的經緯度
geopos key member [member ...]
geopos cities:locations tianjin
# 獲取兩個地理位置的距離
geodist key member1 member2 [unit]
# unit:m(米)、km(千米)、mi(英里)、ft(尺)
持久化
RDB
# 觸發持久化的,三種機制,手動執行命令
save(同步),會阻塞
bgsave(異步),開啓一個子進程去調用fork函數,去執行拷貝,拷貝好之後新文件替換掉老文件
自動
# 通過配置
save 60 1000 # 在60秒內,變了1000次數據,就執行bgsave
AOF
# 持久化的三種策略
always:不丟失數,但IO開銷較大,一般的sata盤之後幾百TPS
everysec:每秒一次fsync,缺點,丟一秒數據(一般採用這種方式)
no:不用管,缺點,不可控
# AOF重寫
比AOF原生好,可以把過期的數據去掉,把多條命令可以合爲一條
作用·:減少硬盤佔用量,加速恢復速度
# AOF重寫實現兩種方式
bgrewriteaof
AOF重寫配置
RDB和AOF的比較
子進程開銷和優化
1.CPU:
開銷:RDB和AOF文件生成,屬於CPU密集型
優化:不做CPU綁定,不和CPU密集型部署
2.內存:
開銷:fork內存開銷,copy-on-write
優化:echo never > /sys/kernel/mm/transparent_hugepage/enabled
3.硬盤:
開銷:AOF和RDB文件寫入,可以結合iostat,iotop分析
硬盤優化
1.不要和高硬盤負載服務部署一起:存儲服務,消息隊列等
2.no-appendfsync-on-rewrite = yes
3.根據寫入量決定磁盤類型:例如ssd
主從複製
主從複製的簡單總結
1.一個master可以有多個slave
2.一個slave只能有一個master
3.數據流向是單向的,master到slave
實現主從複製
# 命令實現-主從複製
slaveof 127.0.0.1 6379 # 6379爲主
# 命令實現-取消複製
slaveof no one
# 修改配置
slaveof ip port # 綁定的ip是主,本身爲從
slave-read-only yes
主:用來寫
從:用來讀,不能用來寫,會報錯
故障處理
# slave宕機
這個好說,直接在弄一個從的綁到主上
# master宕機
把從的slave,改爲master(slaveof no one),把其他從的在綁定到該主
開發與運維中的問題
讀寫分離
1.讀寫分離:讀流量分攤到從節點
2.可能遇到問題:
複製數據延遲
讀到過期數據
從節點故障
主從配置不一致
1.例如maxmemory不一致:丟失數據
2.例如數據結構優化參數(例如hash-max-ziplist-entries):內存不一致
規避全量複製
1.第一次全量複製
第一次不可避免
小主節點、低峯
2.節點運行ID不匹配
主節點重啓(運行ID變化)
故障轉移,例如哨兵或集羣
3.複製積壓緩衝區不足
網絡中斷,部分複製無法滿足
增大複製緩衝區配置rel_backlog_size,網絡“增強”
規避複製風暴
1.單主節點複製風暴:
問題:主節點重啓,多從節點複製
解決:更換複製拓撲
2.單機器複製風暴
機器宕機後,大量全量複製
主節點分散多機器
Redis Sentienl[哨兵]
在原主從複製基礎上
Redis Sentienl故障轉移
1.多個sentinel發現並確認master有問題
2.選舉出一個sentinel作爲領導
3.選出一個slave作爲master
4.通知其餘slave成爲新的master的slave
5.通知客戶端主從變化
6.等待老的master複製成爲新master的slave
Redis Sentienl的配置
port 26379
daemonize yes
dir "/tmp/redis-4.0.7/data"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
# 啓動
redis-sentinel sentinel.conf
客戶端連接
# 現在就不是直連redis-server了,而是連接redis-sentienl(這樣可以自動實現故障轉移,實現高可用)
遍歷sentinel節點集合,獲取一個可用的sentinel節點,會返回一個master地址,實際連的就是master
客戶端接入流程
1.sentinel地址集合:獲取一個可用的sentinel節點,會返回一個master地址
2.masterName:校驗該master是否是真的master節點
3.不是代理模式,是直接連接的master
內部有三個定時任務
1.每10秒每個sentinel對master和slave執行info
發現slave節點
確認主從關係
2.每2秒每個sentinel通過master節點的channel交換信息(pub/sub)
通過__sentinel__:hello頻道交互
交互對節點的“看法”和自身信息
3.每1秒每個sentinel對其他sentinel和redis執行ping
心跳檢測,失敗判定依據
主觀下線和客觀下線
sentinel monitor <masterName> <ip> <port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds <masterName> <timeout>
sentinel down-after-milliseconds mymaster 30000
主觀下線:每個sentinel節點對Redis節點失敗的“偏見”
客觀下線:所有sentinel節點對Redis節點失敗“達成共識”(超過quorum個統一)
sentinel is-master-down-byaddr
領導者選舉
原因:只有一個sentinel節點完成故障轉移
選舉:通過sentinel is-master-down-by-addr命令都希望成爲領導者
1.每個做主觀下線的sentinel節點向其他sentinel節點發送命令,要求將它設置爲領導者
2.收到命令的sentinel節點如果沒有同意通過其他sentinel節點發送的命令,那麼將同意該請求,否則拒絕
3.如果該sentinel節點發現自己的票數已經超過sentinel集合半數且超過quorum,那麼它將成爲領導者
4.如果此過程有多個sentinel節點成爲領導者。那麼將等待一段時間重新進場選舉
故障轉移(sentinel領導者節點完成)
1.從slave節點中選出一個“合適的”節點作爲新的master節點
2.對上面的slave節點執行slave no one命令讓其成功爲master節點
3.向剩餘的slave節點發送命令,讓它們成爲新master節點的slave節點,複製規則和parallel-syncs參數有關
4.更新對原來master節點配置爲slave,並保持對其“關注”,當其恢復後命令它取複製新的master節點
# 選擇“合適的”slave節點
1.選擇slave-priority(slave節點優先級)最高的slave節點,如果存在則返回,不存在則繼續
2.選擇複製偏移量最大的slave節點(複製的最完整),如果存在則返回,不存在則繼續
3.選擇runID最小的slave節點
總結
1.Redis Sentinel是redis的高可用實現方案:
故障發現、故障自動轉移、配置中心、客戶端通知
2.Redis Sentinel從Reids2.8版本開始才正式生產可用,之前版本生產不可用
3.儘可能在不用物理機上部署Redis Sentinel所有節點
4.Reids Sentinel中的Sentinel節點個數應該爲大於等於3,且最好爲奇數
5.Redis Sentinel中的數據節點與普通數據節點沒有區別
6.客戶端初始化時連接的是Sentinel節點集合,不再是具體的Redis節點,但Sentinel只是配置中心不是代理
7.Redis Sentinel通過三個定時任務實現了Sentinel節點對於主節點、從節點、其餘Sentinel節點的監控
8.Redis Sentinel在對節點做失敗判定時分爲主觀下線和客觀下線
9.看懂Redis Sentinel故障轉移日誌對於Redis Sentinel以及問題排查非常有幫助
10.Redis Sentinel實現讀寫分離高可用可以依賴Sentinel節點的消息通知,獲取Redis數據節點的狀態變化