目录
主要功能
慢查询
生命周期
如图所示为客户端请求到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]
举例:独立用户统计
需求:
- 使用set和Bitmap
- 有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以内的城市