1. 程式人生 > 其它 >Redis(慢查詢, pipeline, 釋出訂閱, Bitmap, HyperLogLog, GEO) 學習筆記

Redis(慢查詢, pipeline, 釋出訂閱, Bitmap, HyperLogLog, GEO) 學習筆記

Redis(慢查詢, pipeline, 釋出訂閱, Bitmap, HyperLogLog, GEO)

1. 慢查詢

客戶端請求的生命週期

兩個配置

配置

  • slowlog-max-len 慢查詢佇列最大長度

    1. 先進先出佇列
    2. 固定長度(佇列滿了後會以先進先出的方式,保證佇列的固定長度)
    3. 儲存在記憶體中(不會持久化,重啟消失)
  • slowlog-log-slower-than 慢查詢閾值

    1. 慢查詢閾值(單位:微妙)
    2. slowlog-log-slower-than=0 記錄所有命令 (排查問題時,檢視執行查詢命令時會使用)
    3. slowlog-log-slower-than<0 不記錄任何命令

配置方法

  1. 預設值
    • config get slowlog-max-len = 128
    • config get slowlog-log-slower-than = 10000
  2. 修改配置檔案重啟
  3. 動態配置
    • config set slowlog-max-len 1000
    • config set slowlog-log-slower-than 1000

3個命令

  • slowlog get [n]: 獲取慢查詢佇列
  • slowlog len: 獲取慢查詢佇列長度
  • slowlog reset: 清空慢查詢佇列

運維經驗

  1. slowlog-log-slower-then 不要設定過大,預設10ms, 通常設定1ms(1000)
  2. slowlog-max-len 不要設定過小,通常設定1000左右
  3. 理解命令生命週期(綜合考慮 網路 慢查詢 QPS 等因素)
  4. 定期持久化慢查詢(通過 slowlog get [n] 命令獲取慢查詢記錄,然後儲存到其他的資料中)

2. pipeline 流水線

什麼是流水線?

流水線作用

對比 pipeline 的使用

  1. 不使用 pipeline

  2. 使用 pipeline

pipeline 使用建議

  1. 注意每次 pipeline 攜帶資料量
  2. pipeline 每次只能作用在一個 Redis 節點上
  3. M操作(mget, mset)命令和 pipeline 的區別
    1. M操作(mget, mset)命令的執行是原子的,本身就是一條原生的命令
    2. pipeline 是執行多條命令,不具備原子性

3. 釋出訂閱

角色

  1. 釋出者(publisher)
  2. 訂閱者(subscriber)
  3. 頻道(channel)

模型

API

publish (釋出)

  • publish channel message
    # 示例
    127.0.0.1:6382> publish sohu:tv "hello world"
    (integer) 0       # 表示訂閱個數, 0 表示沒有訂閱者
    127.0.0.1:6382> publish sohu:tv "hello"
    (integer) 3       # 表示訂閱個數, 3 表示有3個訂閱者
    

subscribe (訂閱)

  • subscribe [channel]: 訂閱1個或多個頻道
    127.0.0.1:6382> subscribe sohu:tv cctv1
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "sohu:tv"
    3) (integer) 1
    1) "subscribe"
    2) "cctv1"
    3) (integer) 2
    
    1) "message"
    2) "sohu:tv"
    3) "hello"
    
    1) "message"
    2) "cctv1"
    3) "hello"
    

unsubscribe (取消訂閱)

  • unsubscribe [channel]: 取消訂閱1個或者多個頻道
    127.0.0.1:6382> unsubscribe sohu:tv
    1) "unsubscribe"
    2) "sohu:tv"
    3) (integer) 0
    

    疑問:為什麼在 redis-cli 中使用了 subscribe 命令之後無法再執行 unsubscribe 等的命令
    https://nicechiblog.com/article/21/article_1598666045913.html

其他

  • psubscribe [pattern]: 訂閱模式(匹配頻道)
  • punsubscribe [pattern]: 退出指定的模式(指定匹配模式)
  • pubsub channels: 列出至少有一個訂閱者的頻道
  • pubsub numsub [channel...]: 列出給定頻道的訂閱者數量
  • pubsub numpat: 列出被訂閱模式的數量

對比釋出訂閱與訊息佇列

  • 訊息佇列模式

總結

  1. 明白髮布訂閱模式中的角色
  2. 明白重要的API
  3. 明白髮布訂閱和訊息佇列的使用場景

4. Bitmap (點陣圖)

點陣圖介紹

127.0.0.1:6382> set hello big
OK
127.0.0.1:6382> get  hello
"big"
127.0.0.1:6382> getbit hello 0
(integer) 0
127.0.0.1:6382> getbit hello 1
(integer) 1
127.0.0.1:6382> getbit hello 2
(integer) 1
127.0.0.1:6382> getbit hello 3
(integer) 0
127.0.0.1:6382> getbit hello 6
(integer) 1
127.0.0.1:6382> getbit hello 7
(integer) 0

相關命令

  • setbit key offset value : 給點陣圖指定索引設定值

    # big '01100010 01101001 01100111'
    127.0.0.1:6382> set hello big
    OK
    127.0.0.1:6382> get  hello
    "big"
    127.0.0.1:6382> getbit hello 0
    (integer) 0
    127.0.0.1:6382> setbit hello 0 1 # 將 hello 的第0個bit設定為1
    (integer) 0                      # 返回值0: 表示修改之前對應位的值是0
    127.0.0.1:6382> getbit  hello 0
    (integer) 1
    127.0.0.1:6382> get hello
    "\xe2ig"
    
    127.0.0.1:6382> set hello big
    OK
    127.0.0.1:6382> get hello
    "big"
    127.0.0.1:6382> setbit hello 7 1
    (integer) 0
    127.0.0.1:6382> get hello
    "cig"
    
  • getbit key offset: 獲取點陣圖指定索引的值

  • bitcount key [start end] : 獲取點陣圖指定範圍位值為1的個數(start 到 end,單位為位元組,如果不指定就是獲取全部)

    注意:start 和 end,單位為位元組

    # big '01100010 01101001 01100111'
    127.0.0.1:6382> set hello big
    OK
    127.0.0.1:6382> bitcount hello
    (integer) 12
    127.0.0.1:6382> bitcount hello 0 1
    (integer) 7
    127.0.0.1:6382>
    127.0.0.1:6382>
    127.0.0.1:6382> bitcount hello 1 1
    (integer) 4
    127.0.0.1:6382> bitcount hello 0 0
    (integer) 3
    127.0.0.1:6382>
    
  • bitop op destkey key [key...]: 做多個 Bitmap 的 and(交集),or(並集),not(非),xor(異或) 操作,並將結果儲存到destkey中

    127.0.0.1:6382> set test1 abc
    OK
    127.0.0.1:6382> set test2 bbc
    OK
    127.0.0.1:6382> set test3 abbd
    OK
    127.0.0.1:6382> bitop and test test1 test2
    (integer) 3
    127.0.0.1:6382> get test
    "`bc"
    127.0.0.1:6382> bitop or test test1 test2
    (integer) 3
    127.0.0.1:6382> get test
    "cbc"
    127.0.0.1:6382> bitop not test test1
    (integer) 3
    127.0.0.1:6382> get test
    "\x9e\x9d\x9c"
    127.0.0.1:6382> bitop and test test2 test3
    (integer) 4              # 結果destkey的位元組數
    127.0.0.1:6382> get test
    "`bb\x00"
    
  • bitpos key targetBit [start] [end]: 計算點陣圖指定範圍(start到end,單位為位元組,如果不指定就是獲取全部)第一個偏移量對應的值等於targetBit的位置

    # big '01100010 01101001 01100111'
    127.0.0.1:6382> get hello
    "big"
    127.0.0.1:6382> bitpos hello 1
    (integer) 1
    127.0.0.1:6382> bitpos hello 1 1 2
    (integer) 9
    

獨立使用者統計 (點陣圖的簡單使用)

  1. 使用 set 和 Bitmap 對比

  2. 1億使用者,5千萬獨立訪問

Bitmap 使用經驗

  1. type=string, 最大512MB
  2. 注意setbit時的偏移量,可能有較大耗時
  3. 點陣圖不是絕對好

5. HyperLogLog

新的資料結構?

  1. 基於 HyperLogLog 演算法:極小空間完成獨立數量統計
  2. 本質還是字串
    127.0.0.1:6382> pfadd web "u1"
    (integer) 1
    127.0.0.1:6382> type web
    string
    

三個命令

  1. pfadd key element [element...]: 向 hyperloglog 新增元素

  2. pfcount key [key...] : 計算 hyperloglog 的獨立總數

  3. pfmerge destkey sourcekey [sourcekey...]: 合併多個 hyperloglog

    127.0.0.1:6382> pfadd 20200601:unique:ids "uuid-1" "uuid-2" "uuid-3" "uuid-4"
    (integer) 1
    127.0.0.1:6382> pfadd 20200602:unique:ids "uuid-4" "uuid-5" "uuid-6" "uuid-7"
    (integer) 1
    127.0.0.1:6382> pfcount 20200602:unique:ids
    (integer) 4
    127.0.0.1:6382> pfcount 20200601:unique:ids 20200602:unique:ids
    (integer) 7
    127.0.0.1:6382> pfmerge 202006_01_02:unique:ids 20200601:unique:ids 20200602:unique:ids
    OK
    127.0.0.1:6382> pfcount 202006_01_02:unique:ids
    (integer) 7
    

記憶體消耗(百萬獨立使用者)

使用經驗

  1. 是否能容忍錯誤率?(錯誤率:0.81%)

    百萬獨立使用者統計結果:

  2. 是否需要單條資料?

6. GEO

GEO 是什麼

應用場景

5個城市的經緯度

相關命令

  1. geoadd key longitude latitude member [longtitude latitude member ...] : 新增地理位置資訊

    127.0.0.1:6382> geoadd cities:locations 116.28 39.55 beijing
    (integer) 1     # 新增1個member
    127.0.0.1:6382> geoadd cities:locations 116.28 39.55 beijing
    (integer) 0     # 新增0個member (重複不會新增)
    127.0.0.1:6382> geoadd cities:locations 117.12 39.08 tianjing 114.29 38.02 shijiazhuang 118.01 39.38 tangshan 115.29 38.51 baoding
    (integer) 4     # 新增4個member
    
  2. geopos key member [membet ...]: 獲取地理位置

    127.0.0.1:6382> geopos cities:locations beijing
    1) 1) "116.28000229597091675"
       2) "39.5500007245470826"
    127.0.0.1:6382> geopos cities:locations beijing baoding
    1) 1) "116.28000229597091675"
       2) "39.5500007245470826"
    2) 1) "115.28999894857406616"
       2) "38.50999956342798924"
    127.0.0.1:6382>
    
  3. geodist key member1 member2 [unit]: 獲取兩個地理位置的距離

    127.0.0.1:6382> geodist cities:locations beiji ng tianjin km
    "89.2061"
    
  4. georadius georadiusbymember 獲取指定範圍內的地理位置資訊集合:

    • georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]
    • georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]
      • wihcoord: 返回結果包含經緯度
      • withdist: 返回結果包含距離中心節點位置
      • withhash: 返回結果中包含geohash
      • Count count: 指定返回結果的數量
      • asc|desc: 返回結果按照距離中心節點的距離做升序、降序
      • store key: 將返回結果的地理位置資訊儲存到指定key
      • storedist key: 將返回結果距離中心節點的距離儲存到指定key
    127.0.0.1:6382> georadiusbymember cities:locations beijing 150 km
    1) "beijing"
    2) "tianjin"
    3) "tianjing"
    4) "tangshan"
    5) "baoding"
    

相關說明

  1. redis 3.2+ 提供功能
  2. type geoKey = zset
    127.0.0.1:6382> type cities:locations
    zset
    
  3. 沒有刪除API(使用有序集合的刪除命令): zrem key member