天天看點

分布式|玩轉redis看這一篇就夠了,輕輕松松應對各種面試難題

資料存儲類型介紹

業務資料的特殊性

作為緩存使用

  • 原始業務功能設計
    • 秒殺
    • 618活動
    • 雙11活動
    • 12306

附加功能

  • 系統功能優化更新
    • 單伺服器更新叢集
    • session管理
    • Token管理

Redis資料類型(5種常用)

  • string      string
  • hash      HashMap
  • list      LinkedList
  • set      HashSet
  • sorted_set      TreeSet

string

  • get key
  • set key
  • del [key]
  • mset key1 value1 key2 value2
  • mget key1 key2
  • strlen key
  • append key value

單資料操作與多資料操作的選擇之或?

  • 比較發送與執行時間消耗時間對比

string資料類型的擴充操作

  • 設定數值資料新增加指定範圍的值,可以使用負号作為遞減操作
  • incr key
      incrby key increment
      incrbyfloat key increment
               
  • 設定數值資料新減去指定範圍的值
  • decr key
      decrby key increment
               
  • 設定數值有效期 解決時效性控制的操作
  • setex key second value   秒
      psetex key milliseconds value 毫秒
               

string類型資料操作時的注意事項

  • 設定數值有效期 解決時效性控制的操作
    1. 資料未擷取到
  • (nil)等于 null
               
    1. 資料最大存儲量

      512m

    2. 資料計算最大範圍 (java中的long的最大值)

      9223372036854775807

string類型應用場景

  • 在redis中存儲使用者資訊
    1. user🆔333:fans -> 11111 數值
    2. user🆔333 -> {id:333,fans:333} json
  • redis應用于各種結構性和非結構性高熱度資料通路的加速
  • key的設定約定 表名:主鍵名:主鍵值:字段名

hash

底層使用哈希表結構存儲

hash存儲結構優化

  • 如果field字段數量少,使用資料數組進行存儲
  • 如果field字段數量多,存儲結構使用hashmap

hash類型資料的基本操作

  • 添加/修改資料
  • hset key field value
               
  • 擷取資料
  • hget key field
      hgetall key
               
  • 删除資料
  • hdel key field [field2]
               
  • 添加/修改多個資料
  • hmset key field1 value1 field2 value2
               
  • 擷取多個資料
  • hmget key filed1 field2
               
  • 擷取hash表中字段的數量
  • hlen key
               
  • 擷取hash表中是否存在指定字段
  • hexists key field
               

hash資料類型的擴充操作

  • 擷取hash表中所有的字段名和值
  • hkeys key
    hvalues key
               
  • 設定值自增
  • hincrby key increment
    hincrbyfloat key increment
               
  • 設定值字元,存在則設定失敗,不存在則設定成功
  • setnx key field value
               

hash資料類型注意事項

  • hash類型value隻能存字元串
  • 每個hash可以存儲2^32-1個鍵值對
  • hash可以靈活操作屬性,雖然可以作為對象使用,但是不能濫用
  • hgetall key 擷取hash内的鍵值對

hash資料類型應用場景

  • 購物車

list

list類型資料的基本操作 連結清單

  • 添加/修改資料
  • lpush key value [value]
    rpush key value [value]
               
  • 擷取資料
  • lrange key start stop (0,-1擷取全部)
    lindex key index
    llen key
               
  • 擷取并移除資料
  • lpop key
    rpop key
               
  • 規定時間内擷取并移除資料
  • blpop key [key] timeout (機關為秒)
    brpop key [key] timeout (機關為秒)
               

業務場景

  • 删除指定元素
  • lrem key count value
               

list資料類型注意事項

  • list資料儲存的資料都是string類型,最多2^32-1個元素
  • list常被用作隊列
  • list結束索引為-1
  • list可以進行資料分頁操作 第一頁來自list,第二頁及更多來自資料庫

業務場景

  • 資訊管理
  • 多路資訊彙總
  • 最新消息

set 無序

set類型資料的基本操作

  • 添加資料
  • sadd key memeber1 [member]
               
  • 擷取全部資料
  • smembers key
               
  • 删除資料
  • srem key member1 [member]
               

set類型資料的擴充操作

  • 随機擷取幾個元素
  • srandmember key count
               
  • 随機擷取幾個元素 并删除
  • spop key count
               
  • 擷取元素個數
  • scard key
               
  • 求兩個集合的交并差
  • sinter key key2
      sunion key1 key2
      sdiff key1 key2
               
  • 求兩個集合的交并差 并存到指定集合
  • sinterstore desc key key2
      sunionstore desc key1 key2
      sdiffstore desc key1 key2
               
  • 将指定資料從原始集合移動到目标集合中
  • smove source desc member
               
  • 檢視資料是否存在
  • sismember key memeber
               

業務場景

  • 随機推薦和抽獎等

zset 有序

zset類型資料的基本操作

  • 添加資料
  • zadd key score memeber1
               
  • 查詢
  • zrange key start stop [withscores]
               
  • 查詢 反序
  • zrevrange key start stop [withscores]
               
  • 删除
  • zrem key memeber [member]
               

資料類型實戰

  • 限流 如果限流為100 則把最大值-100,利用異常做限制,不需要每次進行判斷

通用指令

  • 删除key del key
  • key的類型 type key
  • key是否存在 exists key
  • 為key設定有效期
  • expire key  seconds
     pexpire key millseconds
      expireeat key timestamp
      pexpireeat key mill-timestamp
               
  • 擷取key有效時間
  • ttl key
      pttl key
               
  • 切換key從臨時轉為永久
  • persist key
               
  • 查詢模式
  • keys *  比對所有
      keys ?lezai 比對單個字元
      keys a[abc]  比對aa ab ac
               
  • key重命名
  • rename key new key
      renamenx key newkey 新key不存在則成功
               
  • 對所有key 裡面的内容排序
  • sort key 
               
  • 切換資料庫
  • select dbindex
      ping pong
               
  • 資料庫移動
  • mv key  dbindex
      flushdb 删除目前庫資料
      flushall 清除所有資料
               

Jedis

  • 用戶端連接配接redis
  • 連接配接 Jedis jedis =new Jedis("127.0.0.1",6379)
      設定 jedis.set("name",123)
      擷取 jedis.get("name")
               

Linux安裝redis

  • 下載下傳 wget http://download.redis.io/releases/redis-4.0.10.tar.gz
  • 解壓 tar-xvzf redis-4.0.10.tar.gz
  • 編譯 make
  • 安裝make install
  • 指定端口啟動 redis-server --port 9999
  • 指定端口連接配接 redis-cli -p 9999
  • 指定配置檔案啟動 redis-server conf/redis.conf
redis服務端基本配置
  • daemonize yes 以守護程序方式啟動
  • port 6379 設定啟動端口
  • dir “/redis/data” 設定目前服務檔案儲存位置
  • logfile “744.log” 設定日志檔案名
持久化

RDB

  • save 手動執行儲存一次快照資訊
  • 相關配置
  • dbfilename dump.rdb 設定本地資料庫檔案 預設為dump.rdb 一般設定為 dump-端口号.rdb
      rdbcompression yes 是否啟動壓縮
      rdbchecksum yes 是否對庫檔案進行校驗
               
  • bgsave 使用fork函數生成一個子程序,在子程序中執行
  • rdb自動啟動定時儲存
  • 配置資訊 save second changenum
      save 900 1  900 秒内有一個key變化
      save 60 3 60秒内有3個key變化
      save 10 6
               

AOF

寫資料的三種政策

  • always 每次操作都同步寫入到aof中,資料零誤差 性能低
  • everysec 每秒 将緩沖區的指令同步到aof中,系統當機隻會丢失一秒的資料
  • no 系統控制 不可控

AOF功能開啟

  • appendonly yes | no 開啟持久化 預設不開啟
  • appendfsync always | everysec | no AOF政策
  • appendfilename fielname

AOF重寫 重寫規則

  • 程序内已逾時的資料不再重寫
  • 忽略無效指令
  • 對同一資料的多條寫合并為一條
  • bgrewriteaof 重寫aof指令

AOF 與RDB 選擇

  • 資料很敏感 使用aof
  • 資料間斷性呈現 RDB
  • 綜合方案 同時開啟rdb+aof

Redis進階操作

Redis事務

事務的基本操作
  • 開啟事務
  • multi 設定事務的開啟 執行指令後,全都加入到事務中
               
  • 執行事務
  • exec 設定事務的結束,同時執行事務,與multi成對出現
               
  • 取消事務
  • discard 取消事務
               
  • 注意
  • 事務出錯不能復原,産生的資料不會復原
               

  • watch key1 key2 …
  • 監控某個key,需要在事務外面使用,如果key被外部修改了,則終止事務的執行
               
  • unwatch
  • 取消對事務的監控
               

分布式鎖

  • setnx key value

解決死鎖 添加時效性

Redis删除政策

定時删除

  • 建立一個定時器,當key設定有過期時間,且過期時間到達,由定時器執行對鍵的删除操作
  • 犧牲CPU保證記憶體空間 CPU空閑 記憶體緊張

惰性删除

  • 在擷取資料的時候,如果未過期,傳回資料,過期了,删除,傳回不存在
  • 犧牲存儲保證CPU 存儲空間足 CPU緊張

定期删除

定期删除政策是怎麼實作的?通過activeExpireCycle函數,serverCron函數執行時,activeExpireCycle函數就會被調用,規定的時間裡面分多次周遊伺服器的expires字典随機檢查一部分key的過期時間,并删除其中的過期key

例如Redis每秒處理:

  1. 測試随機的20個keys進行相關過期檢測。
  2. 删除所有已經過期的keys。
  3. 如果有多于25%的keys過期,重複步奏1.

Redis逐出算法

  • 在執行每一個指令前,都調用freememoryifneed,記憶體不足,需要臨時删除一些資料清理空間
  • maxmemory 最大記憶體
  • maxmemory-samples 随機選擇
  • maxmemory-policy
  • 有效期的資料
  • volatile-lru 最近最少使用
               
  • volatile-lfu 最近使用次數最少
               
  • volatile-ttl 挑選将要過期的資料
               
  • volatile-random 任意選擇資料淘汰
               
  • 所有資料
  • allkeys-lru 最近最少使用
               
  • allkeys-lfu 最近使用次數最少
               
  • allkeys-random 任意選擇資料淘汰
               
  • no-enviction

進階資料類型

bitmaps
  • setbits key offset value
  • getbits key offset
  • bitop [and or not xor] destkey key1 key2 對多個key組合操作,儲存到destkey中
  • bitcount key [start end] 統計為1的數量
HyperLogLog
  • pfadd key element …
  • pfcount key
  • pfmerge destkey sourcekey1 sourcekey2
  • 相關說明
  • 用于基數統計,不是集合,不儲存資料,隻記錄數量而不是具體資料
               
  • 核心是基數估算,最終數值存在一定誤差
               
  • 誤差範圍:0.81%
               
  • 占用12k
               
  • pfadd 不是一次性配置設定12看,而是随基數增大而增加空間
               
Geo 距離計算
  • geoadd key longitude latitude member … 添加坐标
  • geopos key member … 擷取坐标
  • geodist key member1 member2 unit 擷取坐标點距離
  • georadius key longitude latitude radius unit 根據坐标求範圍内的資料
  • georadiusbymember key memeber radius unit 根據點求範圍内的資料

Redis叢集

主從複制簡介

網際網路“三高”

  • 高性能
  • 高并發
  • 高可用 5個9 99.999%

工作流程

  • 建立連接配接
  • 資料同步(複制資料)
  • 反複同步(指令傳播)
  • 建立連接配接階段工作流程
  • 1. 發送指令 slaveof ip port
               
  • 2. 接收到指令,響應對方
               
  • 3.儲存master的ip與端口 masterip masterport
               
  • 4.根據連接配接儲存的資訊建立與master的socket
               
  • 5.向master周期發送ping,master相應pong
               
  • 6.slave 發送author password
               
  • 7.驗證授權
               
  • 8.發送指令replyconfiglistening-port port-num
               
  • 9.儲存slave端口号
               
  • 連接配接的三種方式
  • 1.slaveof if ip port
               
  • 2.slave啟動時 帶參數 --slaveof masterip masterport
               
  • 3.伺服器配置 slaveof if ip port
               
  • 資料同步階段
  • 全量複制開始
               
  • ①發送指令 psync2 請求同步資料
               
  • ②master執行bgsave
               
  • ③第一個slave建立連接配接,建立指令緩沖區
               
  • ④生成rdb,通過socket發給slave
               
  • ⑤vslave接受rdb,清空資料,執行rdb檔案恢複
               
  • ⑥發送指令,告知已經恢複完成
               
  • 全量複制結束
               
  • 部分複制開始
               
  • ⑦發送複制緩沖區指令資訊
               
  • ⑧接受指令,執行bgrewriteeaof,恢複資料
               
  • 部分複制結束
               
  • 指令傳播階段
  • 複制緩沖區 偏移量 位元組值
               
  • 工作原理: 通過offset區分不同的slave目前資料傳播的差異,maste記錄已發送的資訊對應的offset,slave記錄已經接受的offset
               

資料同步(全)

  • slave 發送指令 psync ?-1
  • master收到發現沒有偏移量,則使用bgsave生成rdb檔案,記錄目前的複制偏移量offset
  • 發送fullresync runid offset,通過socket發送給slave,期間收到用戶端指令,offset發生變化
  • 收到 + fullresync 儲存master的runid和offset,清空目前資料,接受rdb檔案,執行恢複
  • 發送指令 psync2 runid offset
  • master接受到指令,判定runid是否比對,判定offset是否在緩沖中
  • 如果runid和offset不比對,則執行全量複制
  • 如果runid和master校驗通過,offset和offset相同,忽略
  • 如果runid和master校驗通過,offset和offset不相同, 發送continue offset,通過socket發送緩沖區中offset到offset的資料
  • slave接收到continue,儲存master的offset,接受資訊後,執行bgrewriteaof,恢複資料
  • 主從複制參數注意
  • ① slave-server-stable-data yes|no 同步過程,開啟或關閉對外寫操作
               
  • ②repl-backlog-size 1mb 設定master指令緩沖區大小,
               
  • 主從複制常見問題

    頻繁全量複制

  • ①緩沖區太小 導緻offset不比對 解決:緩沖區設定大點
               
  • ②maset當機重新開機,導緻runid和offset丢失,全量複制 master執行shutdown 時,将runid和offset進行儲存,重新開機時進行讀取
               
    頻繁網絡中斷
    ① 執行指令一直阻塞耗時  設定逾時時間
               
    資料不一緻

哨兵簡介

哨兵是一個分布式系統,用于對主從結構中的每台伺服器做監控,當出現故障通過投票随機選擇新的master并将所有的slave連接配接到資訊master

作用

  • 監控
  • 通知
  • 自動故障轉移

啟用哨兵模式

  • 啟動哨兵
  • redis-sentinel redis-sentinel.conf
               
  • 配置檔案中配置 主redis節點
               

哨兵工作原理

監控階段

  • 用于同步各個節點的狀态資訊
    • 擷取sentinel的狀态(是否線上)
    • 擷取master狀态
    • 擷取所有slave狀态
    • master儲存sentinel資訊,作用是讓其他sentinel來發現其他的sentinel,建立訂閱通道

通知階段

  • 每個sentinel進行互通

故障轉移階段

  • sentinel發現master關挂了,标記master為主觀下線,然後發送指令給奇特哨兵,其他哨兵也會去看看狀态,如果一半以上的哨兵認為master挂了,那就直接标記為客觀下線,執行故障轉移操作
  • sentinel通過競選,然後獲得此次處理master的權利,成為領頭sentinel
    • 去除不線上的
    • 去除響應慢的
    • 與原master斷開時間久的
    • 優先原則
      • 優先級
      • offset
      • runid
  • 發送指令
    • 向新的master發送slave no one指令
    • 向其他slave發送slaveof新的ip端口

叢集簡介

資料存儲設計

  • 通過算法設計,計算出key應該儲存的位置
  • 将所有的存儲空間分割成16384份,每台主機儲存一部分代表的是一個存儲空間,不是一個key的儲存空間
  • 将key按照計算的結果放到對應的存儲空間

叢集内部通訊設計

  • 各個節點互相通信,儲存各個庫中槽的編号資料
  • 一次命中,直接傳回
  • 一次未命中,告知具體位置

環境搭建

  • cluster-enabled yes
  • cluster-config-file node-6379.conf
  • cluster-node-timeout 10000
  • 在src下執行
  • ./redis-trib.rb create --replicas 1(一個master,一個slave,2 一個master兩個slave)  主[...] 從[...]
               
  • 連接配接叢集用戶端
  • redis-cli -c
               

企業級解決方案

緩存預熱

系統啟動前,提前将相關的緩存資料直接加載到緩存系統,避免在使用者請求的時候,先查詢資料庫,然後再将資料緩存的問題,使用者直接查詢事先被預熱的資料

緩存雪崩

緩存擊穿

緩存穿透

解決方案

  • 緩存null
  • key加密
  • 實時監控
  • 白名單政策 bitmaps(效率低)

繼續閱讀