主要功能

慢查询

生命周期

如图所示为客户端请求到Redis的完整生命周期:发送命令、排队、执行命令、返回结果

配置

有两点说明

  • 慢查询发生在第三阶段(也就是说其他阶段像排队耗时都不算)
  • 客户端超时不一定慢查询,因为这四个过程都可能造成超时,但慢查询是客户端超时的一个可能因素

两个配置

  • slowlog-max-len
    1.配置慢查询队列最大长度
    2.筛选出的慢查询会进入一个先进先出队列,即超出长度时,会踢出最早进来点
    3.该队列是固定长度
    4.该队列是保存在内存

  • slowlog-log-slower-than
    1.慢查询阈值(单位:微秒),也就是说超过多少时间的查询是慢查询
    2.slowlog-log-slower-than=0; 记录所有命令
    3.slowlog-log-slower-than<0; 不记录任何命令

配置方法

  • 默认值
    config get slowlog-max-len = 128
    config get slowlog-log-slower-than = 10000,即10毫秒
    修改配置文件重启(不建议,因为生产环境要尽量避免重启,在第一次启动redis前可以这么做)
  • 动态配置
    config set slowlog-max-len 1000
    config set slowlog-log-slower-than 1000

三个命令

  • slowlog get [n]: 获取慢查询队列(n为可选参数,指定慢查询条数)
  • slowlog len: 获取慢查询队列长度
  • slowlog reset: 清空慢查询队列

运维经验

  • slowlog-log-slower-than不要设置过大,默认10ms,<mark>通常设置1ms</mark>
  • slowlog-max-len不要设置过小,通常设置1000左右
  • 理解命令生命周期
  • 定期持久化慢查询(方便查到历史慢查询操作)

pipeline

介绍

什么是流水线

  • 对比: 1次网络命令通信模型 vs 批量网络命令通信模型

执行redis命令时间通常是非常快的,而网络则存在很多不稳定因素。另外redis虽然提供了mget、mset和hmget、hmset等这样的命令,但是如果我们需要同时执行get和hget命令需要怎么做呢,其实这就是流水线帮助我们实现的功能。

流水线就是将一批命令进行一个打包,而在服务端进行批量的计算,然后按顺序将结果返回给客户端,使用流水线可以大大节省网络的开销。

<mark>使用pipeline实现,每次执行100个命令,执行100次pipeline操作,最终时间只需要0.7秒</mark>

与原生M操作

  • 与原生M操作对比,M操作是一个原子操作,只需要执行和计算一次
  • pipeline是将命令进行打包,传送到redis时,则会拆分成子命令,结果会按顺序返回。

使用建议

  • 注意每次pipeline携带数据量(数据量过大需合理拆分次数)
  • pipeline每次只能作用在一个Redis节点上
  • 明确M操作与pipeline区别

发布订阅

简介

角色

  • 角色主要有发布者(publisher)、订阅者(subscriber)、频道(channel)

  • 流程发布者会发布消息到频道上,订阅者通过订阅频道来获取消息。

  • 类似一些新闻APP(微信公众号),只要订阅了某些频道,这些频道有新消息发布订阅者就能收到消息。

模型

模型如图所示(类似生产者与消费者模型),对于订阅者而言其实也是个客户端,订阅者是可以订阅多个频道的,有个问题就是假如发布者已经发布了一条消息到频道中,但是一个新的订阅者是收不到之前已经发送过的消息的,使用时一定要注意这种场景,就是说redis并没有提供消息堆积的功能,所以无法获取历史消息。

需要注意一点:<mark>不具备消息堆集的能力,即新订阅的无法查看原来的消息</mark>

相关API

发布消息publish channel message

订阅频道subscribe [channel]

  • 返回信息:订阅了哪个频道,收到消息详细信息

取消订阅unsubscribe [channel]


其他API,例如第一个命令根据pattern去匹配订阅,如: v*,匹配v开头的频道

消息队列 VS 发布订阅

  • 发布订阅是所有的订阅者都能接受到
  • 消息队列是只有一个订阅者能接受到

总结:

  • 需要注意发布订阅的三个角色:发布者订阅者频道
  • 重要的API
  • 发布订阅和消息队列的区别

Bitmap(位图)

简介

  • 每个字符串对应的有其ASCII码,将ASCII码转换成对应的二进制,二进制每个数字代表位,即bit
  • bitmap就是可以用来对位进行操作

相关API

设置位图setbit key offset value

  • 最终效果,设置对应的位为对应的值,其他都用0补充

如果对刚才的user执行setbit key 50 1,那么从19位到49位全部补0。这个过程本身会比较慢,<mark>所以在执行 setbit 命令时最好不要在很短的位图上做很大的偏移量。</mark>

获取位图getbit key offset

范围获取bitcount key [start end]

  • 注意start和end指定的是字节,<mark>1个字节代表8位</mark>
  • 如0 0代表第一个字节,即0-7位,1 2代表第二个字节到第三个字节,即8-23位

多位图操作bitop op destkey key[key...]

  • op代表操作符,比如and、or,返回值为操作后的值字节长度
    获取索引bitpos key targetBit [start] [end]

举例:独立用户统计

需求

  1. 使用set和Bitmap
  2. 有1亿用户,5千万独立(每天有5千万人独立访问)

思路

  • 使用位图实现的思路就是,每个用户的ID占一位,比如用户的ID为10000,那我们就将key的第1万位设置为1。
  • 当然这里内存只是个预估值,如果每天都要进行统计,使用位图还是能节省非常大的内存开销的。

  • 那么是不是说在做这样的功能的时候 set 就完全不如 bitmap 好呢。其实是没有完美绝对的事情。
  • <mark>假设只有100万独立用户呢,可以看到使用set会更节省内存,所以使用bitmap也不是绝对的好</mark>

总结

  • 位图是在对位进行操作,实际类型是String,值最大可以存储512MB,对于大部分的独立用户统计应该都可以满足
  • 不要有过大的偏移量,会造成阻塞
  • 当用户量比较小时使用set,用户量大的时候可以使用位图

HyperLogLog

  • 基于HyperLogLog算法:<mark>使用极小空间完成独立数量统计</mark>
  • 本质还是字符串:type hyperloglog_key (返回的是string)

三个命令

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

总结

  • 内存消耗非常小,但是<mark>错误率比较大</mark>
  • 无法获取单条数据

GEO

简介

  • 用来计算地理位置信息相关的功能
  • GEO(地理信息定位):存储经纬度计算两地距离范围计算

应用场景

  • 比如实现类似微信摇一摇这样的功能(社交)
  • 计算周围酒店、餐馆功能(外卖)

相关API

首先给出5个城市的经纬度

添加地理位置geoadd key lng lat member[lng lat member...]

获取地理位置geopos key memeber[member...]

计算距离geodist key member1 member2 [unit]

获取周边georadius

  • 示例:计算在北京150km以内的城市