Redis的其他功能

瑞士军刀Redis

  • 慢查询
  • pipeline
  • 发布订阅
  • Bitmap
  • HyperLogLog
  • GEO

慢查询

声明周期

2020-04-17_043252

  • 慢查询发生在第三阶段 (执行命令), 其中发送命令和排队导致的响应时延问题并不属于慢查询, 而是由于执行(keys, flushall, flushdb, slow lua script, mutil/exec, operate big value (collection))这些重量级的命令导致的问题.
  • 客户端超时不一定是慢查询, 但慢查询是客户端超时的一个可能因素.
  • 我们可以使用 slowlog(慢查询)功能找出最耗时的 Redis 命令进行相关的优化,以提升 Redis 的运行速度,慢查询有两个重要的配置项.

两个配置

  • slowlog-max-len

    • 表示慢查询日志的条数
    • 慢查询队列是一个先进先出队列, 当队列超过长度将会剔除最先入队的慢查询信息
    • 慢查询队列是一个固定长度的队列(可通过配置文件或者命令修改此长度)
    • 慢查询队列保存在内存中, 将随着内存的

    2020-04-17_045300

  • slowlog-log-slower-than

    • 慢查询阈值 (单位: 微秒), 执行超过这个时间的命令将被记录到慢查询日志
    • slowlog-log-slower-than = 0, 记录所有命令
    • slowlog-log-slower-than < 0, 不记录任何命令

配置方法

默认值

127.0.0.1:6379> config get slowlog-max-len
1) "slowlog-max-len"
2) "128"
127.0.0.1:6379> config get slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "10000"
  • 修改配置文件重启

    • 不推荐, 当首次运行时可以使用此操作, 运行时是支持动态配置的
  • 动态配置

    127.0.0.1:6379> config set slowlog-max-len 1000
    OK
    127.0.0.1:6379> config set slowlog-log-slower-than 1000
    OK

慢查询命令

  • slowlog get [n] : 获取慢查询队列
  • slowlog len : 获取慢查询队列长度
  • slowlog reset : 清空慢查询队列

运维经验

  • slowlog-log-slower-than 不要设置过大, 默认10ms, 通常设置1ms, 通过QPS来确定此参数

  • slowlog-max-len 不要设置过小 (设置过小不利于慢查询日志分析), 通常设置1000左右

  • 理解命令声明周期

  • 定期持久化慢查询, 因为慢查询记录在内存中(队列长度和内存重启都可能导致慢查询日志丢失), 可以利用slowlog get命令来持久化到硬盘上

Pipeline

1次网络命令通信模型

2020-04-18_015638

批量网络命令通信模型

2020-04-18_015744

什么是流水线

2020-04-18_015833

流水线的作用

2020-04-18_015927

注意:

  • Redis的命令时间是微秒级别. (网络命令传输是Redis执行效果的瓶颈之一)
  • Pipeline每次条数要控制 (网络).

2020-04-18_020211

Pipeline - Jedis实现

  • 执行10000条命令时:

没有pipeline

2020-04-18_020336

使用pipeline

2020-04-18_020437

Pipeline与原生M操作

原生M操作

2020-04-18_020539

Pipeline

2020-04-18_020635

Pipeline使用建议

  • 注意每次pipeline携带数据量
  • pipeline每次只能作用在一个Redis节点上
  • M操作与pipeline区别

发布订阅

角色

  • 发布者 (publisher)
  • 订阅者 (subscriber)
  • 频道 (channel)

模型

  • 发布者和订阅者都是一个redis客户端
  • 发布者发送一个消息, 订阅该频道的订阅者都可以接受到此消息

2020-04-18_030643

  • 一个订阅者可以同时订阅多个频道

2020-04-18_031044

API

  • publish
  • unsubscribe
  • subscribe
  • 其他

publish (发布命令)

API:

publish channel message

演示:

127.0.0.1:6379> publish sohu:tv "helloworld"
(integer) 2

subscribe (订阅)

API:

subscribe [channel] # 一个或多个

演示:

127.0.0.1:6379> subscribe sohu:tv
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "sohu:tv"
3) (integer) 1
1) "message"
2) "sohu:tv"
3) "helloworld"

unsubscribe (取消订阅)

API:

unsubscribe [channel] # 一个或多个

演示:

127.0.0.1:6379> unsubscribe souhu:tv
1) "unsubscribe"
2) "souhu:tv"
3) (integer) 0

其他API

psubscribe [pattern...] # 订阅模式
punsubscribe [pattern...] # 取消指定的订阅模式
pubsub channels # 列出至少有一个订阅者的频道
pubsub numsub [channel...] # 列出给定频道的订阅者数量

消息队列和发布订阅

2020-04-18_032854

Bitmap

位图

  • Redis可以对存储的数据进行对位操作
  • 示例:
127.0.0.1:6379> set hello big
OK
127.0.0.1:6379> getbit hello 0
(integer) 0
127.0.0.1:6379> getbit hello 1
(integer) 1
127.0.0.1:6379> getbit hello 2
(integer) 1
127.0.0.1:6379> getbit hello 3
(integer) 0

2020-04-18_033106

2020-04-18_033636

API

setbit

API:

# 给位图指定索引设置值
setbit key offset value

演示:

2020-04-18_033914

效果:

2020-04-18_034115

  • 可以做一些独立用户统计的功能
  • 如果只设置索引50, 则位图变为:
    • 注意: 一般不要在一个很短的位图上突然间做一个很大的偏移量, 会引起一些问题 (注意Redis是一个单线程)

2020-04-18_034433

getbit

API:

# 获取位图指定索引的值
getbit key offset

演示:

2020-04-18_034748

bitcount

API:

# 获取位图指定范围(start到end, 单位为字节, 如果不能指定就是获取全部)位值为1的个数
bitcount key [start end]

演示:

2020-04-18_035325

bitop

API:

# 做多个Bitmap的and(交集), or(并集), not(非), xor(异或)操作并将结果保存在destkey中
bitop op destkey key [key...]

演示:

2020-04-18_035705

bitpos

API:

# 计算位图指定范围(start到end, 单位为字节, 如果不能指定就是获取全部)第一个便宜量对应的值等于targetBit的位置
bitpos key targetBit [start] [end]

演示:

127.0.0.1:6379> setbit bitops_key 2 1
(integer) 0
127.0.0.1:6379> setbit bitops_key 4 1
(integer) 0
127.0.0.1:6379> bitcount bitops_key  0 1
(integer) 2
127.0.0.1:6379> bitpos bitops_key 1 
(integer) 2
127.0.0.1:6379> bitpos bitops_key 1 3
(integer) -1

独立用户统计

  • 1亿用户, 5千万独立

set和Bitmap对比

2020-04-18_040613

2020-04-18_040656

  • 只有10万独立用户

2020-04-18_040804

使用经验

  • Bitmap的 type = string, 且最大支持512MB
  • 注意setbit时的偏移量, 可能有较大消耗
  • 位图不是绝对的好, 要根据合理的场景进行使用

HyperLogLog

  • 基于HyperLogLog算法: 极小的空间完成独立数量统计

  • 在Redis中本质还是字符串

    2020-04-18_041943

三个命令

  • pfadd key element [element…] # 向HyperLogLog添加元素
  • pfcount key [key…] # 计算HyperLogLog的独立总数
  • pfmerge destkey sourcekey [sourcekey…] # 合并多个HyperLogLog

演示

2020-04-18_042239

2020-04-18_042317

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

2020-04-18_042422

使用经验

  • 是否能够容忍错误? (错误率: 0.81%)

    • 例如上述百万条数据做如下操作:

    2020-04-18_042632

  • 是否需要单条数据?

    • HyperLogLog不能够获取单条数据

GEO

  • GEO (地理位置信息定位): 存储经纬度, 计算两地距离, 范围计算等

2020-04-18_042908

应用场景

2020-04-18_042958

5个城市经纬度

2020-04-18_043047

API

geoadd

API:

# 增加地理位置信息
geo key longitude latitude member [longitude latitude member...]

演示:

2020-04-18_043309

geopos

API:

# 获取地理位置信息
geopos key member [member...]

演示:

2020-04-18_043514

geodist

API:

# 获取两个地理位置的距离
# unit: m(米), km(千米), mi(英里), ft(尺)
geodist key member1 member2 [unit]

2020-04-18_043816

georadius

API:

2020-04-18_043910

示例:

2020-04-18_044020

相关说明

  • since 3.2 +
  • type geoKey = zset
  • 没有删除API: 可以利用zset实现删除 zrem key member

   转载规则


《Redis的其他功能》 Jiavg 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录