Redis(慢查询, pipeline, 发布订阅, Bitmap, HyperLogLog, GEO) 学习笔记

Redis(慢查询, pipeline, 发布订阅, Bitmap, HyperLogLog, GEO)

1. 慢查询

客户端请求的生命周期

image

两个配置

image

配置

  • 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 流水线

什么是流水线?

image

流水线作用

image

image

对比 pipeline 的使用

  1. 不使用 pipeline

    image

  2. 使用 pipeline

    image

pipeline 使用建议

  1. 注意每次 pipeline 携带数据量
  2. pipeline 每次只能作用在一个 Redis 节点上
  3. M操作(mget, mset)命令和 pipeline 的区别
    1. M操作(mget, mset)命令的执行是原子的,本身就是一条原生的命令
    2. pipeline 是执行多条命令,不具备原子性

3. 发布订阅

角色

  1. 发布者(publisher)
  2. 订阅者(subscriber)
  3. 频道(channel)

模型

image

image

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: 列出被订阅模式的数量

对比发布订阅与消息队列

  • 消息队列模式

    image

总结

  1. 明白发布订阅模式中的角色
  2. 明白重要的API
  3. 明白发布订阅和消息队列的使用场景

4. Bitmap (位图)

位图介绍

image

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"
    

    image

  • 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千万独立访问

    image

    image

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
    

内存消耗(百万独立用户)

image

使用经验

  1. 是否能容忍错误率?(错误率:0.81%)

    百万独立用户统计结果:

    image

  2. 是否需要单条数据?

6. GEO

GEO 是什么

image

应用场景

image

5个城市的经纬度

image

相关命令

  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
posted @ 2022-05-12 12:33  郭赫伟  阅读(59)  评论(0编辑  收藏  举报