1、主從復制
psync-> runid->runid是?則是全量->返回fullresync和runid和復制進度->bgsave命令準備RDB文件->之后的命令寫入replication_buffer->發送RDB->發送replication_buffer的信息
repl_backlog_buffer環型緩沖區,主節點只有一個
psync-> runid->runid在repl_backlog_buffer中則是增量同步->定位repl_backlog_buffer中offset位置->將信息轉到replication_buffer
replication_buffer每個從節點對應一個
2、redis集群
Gossip協議進行節點之間的狀態交換
哈希槽2^14=16384個,因為算法是CRC16計算得出16bit的結果,然后跟2^14取余
MOVED錯誤(返回目標節點的信息,IP+端口)
3、redis線程
核心讀寫是單線程事件驅動模型,網絡是I/O多路復用多線程(同步I/O),默認是禁用的
4、redis數據格式
String :最大512M
hash
list:支持兩端推、彈出數據
set:使用hash表實現
Sorted set/Zset:每個元素都有個評分,用于排序,底層用跳表實現,支持快速的范圍查詢。
bitmap:位圖
hyperloglog:估算集合的基數(cardinality),即集合中不重復元素的數量。誤差在0.81%,用于UV(unique visitor)統計
stream:
5、hash數據的命令
hget/hset/hdel/hmget/hmset/hincrby(全部應該大寫)
6、lua腳本
redis.call和redis.pcall
7、redis的pipeline,最多一次10K個命令
8、redis的大key問題,redis-cli --bigkeys
9、熱點key:
解決熱點key:拆分key,讀寫分離主從復制增加從節點,多級緩存,限流熔斷
查看熱點key:業務經驗、集群監控:QPS傾斜、hotkey監控(實時性不好)、monitor命令(性能損壞特別大)、客戶端收集、代理層收集
10、redis持久化:
RDB(redis database):快照,壓縮的二進制文件,數據恢復不全。
redis.conf文件可以配置在x秒內至少有y個key發生變化會觸發命令進行持久話操作
save命令:在主線程生成RDB文件,主線程無法執行其他命令
bgsave命令:子進程執行RDB生成命令,不會阻塞主線程,但不是完全非阻塞測,默認使用bgsave
AOF(Append Only file):體積大,重寫會消耗更多資源。
混合持久化:aof-use-rdb-preamble配置開啟混合持久化。先生成RDB快照,然后將新的操作追加到AOF文件中。
AOF寫回策略:always(每次寫操作后立即fsync,不能保證數據不丟失,因為是先執行后寫入aof),everysec(每秒調用一次,默認使用這種策略),no(操作系統決定何時寫入)
AOF重寫機制:合理的壓縮寫命令,可以手動觸發BGREWRITEAOF,使用auto-aof-rewrite-min-size和auto-aof-rewrite-percentage自動觸發操作
redis-check-aof工具修復AOF損壞的文件,這個工具會截斷文件中不完整的命令,使其恢復到一致狀態。
寫時復制:當主進程fork出一個子進程后,是讓主進程和子進程共享相同的內存頁面,他們映射同一個物理內存地址。當主進程收到寫命令需要修改數據時,主進程會將對應數據所在的頁復制一份,對復制的副本進行修改。
11、redis哨兵機制:高可用解決方案,完成主從切換
12、redis的主從模式的腦裂
13、redisson看門狗機制:客戶端加鎖后不設置過期時間,而是啟動一個定時任務來檢測鎖,每10s一次,每次續期30s。配置參數為lockwatchdogtimeout
14、redis內存碎片化:默認使用jemalloc內存分配器,需要8K,分配器給12K。使用INFO memory命令查看內存碎片。MEMORY PURGE命令手動清理碎片,但會阻塞主線程。配置activefrag選項,redis可以在運行時嘗試整理內存碎片,合并小的內存。
15、在redis6中使用listpack替換ziplist,因為ziplist在節點中存放了上一個元素的長度,如果長度超過長度記錄的上限,那么可能會引起連鎖更新,非常影響性能
16、redis的watch命令:樂觀鎖機制,但是并不是真正的鎖
17、redis從節點復制緩沖區:client-output-buffer-limit配置間接控制緩沖區大小
18、redis的quicklist:每個quicklist節點都是一個ziplist,相當與限定了ziplist的閾值,當超過ziplist,就用多個ziplist。ziplist+quicklist用于實現redis的鏈表功能
19、redis中list命令:lpush插入隊頭、rpush、lpop、rpop、lrange獲取范圍內元素、lindex通過索引獲取元素、llen列表長度、lset設置制定索引的值、lrem移除列表中參與匹配的元素、ltrim裁剪list使其只包含指定范圍內的元素
ltrim mylist 1 2:保留索引1到2的元素,其他的刪除
lrem mylist 1 a:異常第一個a元素
lrange mylist 0 -1:返回mylist中所有元素
20、redis列表存儲結構:當列表元素較多時使用linked list,便于從兩端快速添加和刪除,如果列表元素較少或總大小較小時,可以使用Ziplist
21、redis中的原生批處理命令:MSET/MGET。他們是原子性的,并且執行速度比pipeline更快(有優化),但是只能用于批量的寫入和讀取鍵值對,靈活性上pipeline更好。但pipeline會占用大量內存,某些redis命令不支持pipeline。
MSET key1 value1 key2 value2 key3 value3
MGET key1 key2 key3
22、redis限制字符串最大只能是512M
23、jedis、lettuce、redisson
24、GEO地理信息:geolocation。底層采用sorted set,每一個地理位置被編碼為一個Geohash值,并使用Geohash的排序特性來存儲在Redis的Sorted Set中,分數則是通過Geohash生成的。Geohash是一種空間編碼方法,將二維地理坐標編碼成一個字符串,這樣在對地理坐標排序時,可以通過Geohash生成的值實現近似的范圍查找
添加地理坐標:GEOADD locations 13.26589 38.65985 "member"
計算地理位置距離:GEODIST locations?"member" "member1" km
查找指定位置附近范圍內的所有點(棄用):GEORADIUS locations 15 37 200 km
以某個已存在位置為中心,查找指定范圍內的地點(棄用):GEORADIUSBYMEMBER locations "member" 100 km?
按長方型或者圓形查找位置:GEOSEARCH用于替代GEORADIUS
將搜索結果存儲到一個新的key中:GEOSEARCHSTORE
25、hyperloglog結構約12K,即使是統計百萬用戶,內存開銷依然是恒定的12K
PFADD key element 添加一個或多個元素
PFCOUNT key 返回HyperLogLog結構中不重復元素的近似數量
PFMERGE?destkey sourcekey 將多個HyperLogLog合并為一個
26、redis中的String類型底層主要基于SDS(Simple Dynamic String),并結合int/embstr/raw等不同的編碼方式進行優化存儲。如果一個字符串可以被解析為整數且數值比較小就會實用int編碼,當字符串長度小于等于44字節,就會實用embstr編碼,將字符串元數據和字符數據放在連續的內存塊中redisObject和sds一起放。當超過44字節,redis會實用raw編碼,這種編碼方式將結構體和實際字符串數據分開存儲,redisObject和sds分開放。
為什么不用C里面的字符串?:獲取長度復雜、結尾用\0表示,字符串操作函數不高效、不安全,可能緩沖區溢出
27、緩存擊穿、緩存穿透、緩存雪崩
28、Red Lock:紅鎖,用于解決在分布式環境中使用Redis實現分布式鎖時的安全性問題,比如主節點宕機,主從切換,從節點沒有同步到鎖信息。使用Red Lock需要至少5個主庫實例,集群部署(不是主從或者哨兵),客戶端對這5個實例依次申請鎖,過半則紅鎖申請成功,反之失敗。紅鎖并非無懈可擊,很多情況會導致失效。
29、redis常用命令合集:
字符串:
# 設置鍵值
SET key value
SET name "張三"
SET age 25# 獲取值
GET key
GET name# 設置過期時間
SETEX key seconds value
SETEX session:123 3600 "user_data"# 批量設置
MSET key1 value1 key2 value2
MSET name "李四" age 30 city "北京"# 批量獲取
MGET key1 key2
MGET name age city# 遞增
INCR key
INCR counter# 遞減
DECR key
DECR counter# 增加指定數值
INCRBY key increment
INCRBY score 10# 追加字符串
APPEND key value
APPEND message " 追加內容"#獲取分布式鎖
SET key value EX seconds NX
哈希操作:
# 設置哈希字段
HSET key field value
HSET user:1 name "王五"
HSET user:1 age 28# 獲取哈希字段
HGET key field
HGET user:1 name# 獲取所有字段
HGETALL key
HGETALL user:1# 批量設置哈希字段
HMSET key field1 value1 field2 value2
HMSET user:2 name "趙六" age 32 email "zhao@example.com"# 批量獲取哈希字段
HMGET key field1 field2
HMGET user:2 name age# 刪除哈希字段
HDEL key field1 field2
HDEL user:1 age# 檢查字段是否存在
HEXISTS key field
HEXISTS user:1 name# 獲取所有字段名
HKEYS key
HKEYS user:1# 獲取所有字段值
HVALS key
HVALS user:1
列表操作:
# 從左側推入
LPUSH key value1 value2
LPUSH queue "任務1" "任務2"# 從右側推入
RPUSH key value1 value2
RPUSH queue "任務3" "任務4"# 從左側彈出
LPOP key
LPOP queue# 從右側彈出
RPOP key
RPOP queue# 獲取列表長度
LLEN key
LLEN queue# 獲取列表元素
LRANGE key start stop
LRANGE queue 0 -1
LRANGE queue 0 2# 根據索引獲取元素
LINDEX key index
LINDEX queue 0# 插入元素
LINSERT key BEFORE|AFTER pivot value
LINSERT queue BEFORE "任務2" "新任務"# 刪除元素
LREM key count value
LREM queue 1 "任務1"
集合操作
# 添加成員
SADD key member1 member2
SADD tags "redis" "database" "cache"# 獲取所有成員
SMEMBERS key
SMEMBERS tags# 檢查成員是否存在
SISMEMBER key member
SISMEMBER tags "redis"# 獲取集合大小
SCARD key
SCARD tags# 刪除成員
SREM key member1 member2
SREM tags "cache"# 隨機獲取成員
SRANDMEMBER key count
SRANDMEMBER tags 2# 集合運算
SUNION key1 key2
SINTER key1 key2
SDIFF key1 key2
SUNION tags1 tags2
有序集合操作:
# 添加成員
ZADD key score member
ZADD leaderboard 100 "玩家1"
ZADD leaderboard 200 "玩家2"# 獲取成員分數
ZSCORE key member
ZSCORE leaderboard "玩家1"# 獲取排名
ZRANK key member
ZRANK leaderboard "玩家1"# 獲取范圍
ZRANGE key start stop
ZRANGE leaderboard 0 -1
ZRANGE leaderboard 0 9# 按分數范圍獲取
ZRANGEBYSCORE key min max
ZRANGEBYSCORE leaderboard 100 200# 獲取集合大小
ZCARD key
ZCARD leaderboard# 刪除成員
ZREM key member
ZREM leaderboard "玩家1"# 增加分數
ZINCRBY key increment member
ZINCRBY leaderboard 50 "玩家1"
鍵操作:
# 檢查鍵是否存在
EXISTS key
EXISTS user:1# 刪除鍵
DEL key1 key2
DEL user:1 user:2# 設置過期時間
EXPIRE key seconds
EXPIRE session:123 3600# 查看剩余過期時間
TTL key
TTL session:123# 獲取所有鍵
KEYS pattern
KEYS user:*
KEYS *# 重命名鍵
RENAME oldkey newkey
RENAME user:1 user:1001# 獲取鍵類型
TYPE key
TYPE user:1
發布訂閱:
# 發布消息
PUBLISH channel message
PUBLISH news "重要新聞"# 訂閱頻道
SUBSCRIBE channel1 channel2
SUBSCRIBE news sports# 取消訂閱
UNSUBSCRIBE channel
UNSUBSCRIBE news# 模式訂閱
PSUBSCRIBE pattern
PSUBSCRIBE news:*
事務操作:
# 開始事務
MULTI# 執行命令
SET key1 value1
SET key2 value2
INCR counter# 執行事務
EXEC# 取消事務
DISCARD# 監視鍵
WATCH key1 key2
MULTI
SET key1 newvalue
EXEC
持久化操作:
# 保存數據到磁盤
SAVE# 異步保存數據到磁盤
BGSAVE# 獲取最后保存時間
LASTSAVE# 獲取Redis信息
INFO# 獲取配置信息
CONFIG GET parameter
CONFIG GET maxmemory