慢查询
生命周期
两个配置
- slowlog-max-len:慢查询队列长度
- slowlog-log-slower-than:慢查询阈值(单位:微秒)
slowlog-log-slower-than=0, 记录所有命令
slowlog-log-slower-than<0, 不记录任何命令
配置方法
-
默认值
- config get slowlog-max-len = 128
- config get slowlog-log-slower-than = 10000
- 修改配置文件重启
-
动态配置
- config set slowlog-max-len 1000
- config set slowlog-log-slower-than 1000
三个命令
- slowlog get [n]:获取慢查询队列
- slowlog len:获取慢查询队列长度
- slowlog reset:清空慢查询队列
运维经验
- slowlog-max-len不要设置过大,默认10ms,通常设置1ms
Redis的QPS是万级的,也就是一条命令平均0.1ms就执行结束了。通常我们翻10倍,设置1ms。 - slowlog-log-slower-than不要设置过小,通常设置1000左右
慢查询队列默认长度128,超过的话,按先进先出,之前的慢查询会丢失。通常我们设置1000。 - 理解命令生命周期
慢查询发生在第三阶段 - 定期持久化慢查询
slowlog get或其他第三方开源工具
pipeline
什么是流水线
未使用pipeline的批量网络通信模型
假设客户端在上海,Redis服务器在北京。相距1300公里。假设光纤速度≈光速2/3,即30000公里/秒2/3。那么一次命令的执行时间就是(13002)/(300002/3)=13毫秒。Redis万级QPS,一次命令执行时间只有0.1毫秒,因此网络传输消耗13毫秒是不能接受的。在N次命令操作下,Redis的使用效率就不是很高了。
使用pipeline的网络通信模型
客户端实现
引入maven依赖
<dependency>
<groupId>redis.clients</groupId>
<artifacId>jedis</artifacId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
// 不用pipeline
Jedis jedis = new Jedis("127.0.0.1", 6379);
for (int i = 0; i < 10000; i++) {
jedis.hset("hashkey" + i, "field" + i, "value=" + i);
}
不用pipeline,10000次hset,总共耗时50s,不同网络环境可能有所不同
// 使用pipeline, 我们将10000条命令分100次pipeline,每次100条命令
Jedis jedis = new Jedis("127.0.0.1", 6379);
for (int i = 0; i < 100; i++) {
Pipeline pipeline = jedis.pipeline();
for (int j = i * 100; j < (i + 1) * 100; j++) {
pipeline.hset("hashkey:" + j, "field" + j, "value" + j);
}
pipeline.syncAndReturnAll();
}
使用pipelne,10000次hset,总共耗时0.7s,不同网络环境可能有所不同。
可见在执行批量命令时,使用pipeline对Redis的使用效率提升是非常明显的。
与M原生操作对比
mset、mget等操作是原子性操作,一次m操作只返回一次结果。
pipeline非原子性操作,只是将N次命令打个包传输,最终命令会被逐条执行,客户端接收N次返回结果。
pipeline使用建议
- 注意每次pipeline携带数据量
pipeline主要就是压缩N次操作的网络时间。但是pipeline的命令条数也不建议过大,避免单次传输数据量过大,客户端等待过长。 - Redis集群中,pipeline每次只作用在一个Reids节点上
发布订阅
角色
- 发布者(publisher)
- 订阅者(subscriber)
- 频道(channel)
模型
订阅者可以订阅多个频道
API
发布
API:publish channel message
redis> publish sohu:tv "hello world"
(integer) 3 #订阅者个数
redis> publish sohu:auto "taxi"
(integer) #没有订阅者
订阅
API:subscribe [channel] #一个或多个
redis> subscribe sohu:tv
1) "subscribe"
2) "sohu:tv"
3) (integer) 1
1) "message"
2) "sohu:tv"
3) "hello world"
取消订阅
API:unsubscribe [channel] #一个或多个
redis> unsubscribe sohu:tv
1) "unsubscribe"
2) "sohu:tv"
3) (integer) 0
其他API
- psubscribe [pattern...] #订阅指定模式
- punsubscribe [pattern...] #退订指定模式
- pubsub channels #列出至少有一个订阅者的频道
- pubsub numsubs [channel...] #列出给定频道的订阅者数量
对比消息队列
消息队列模型
发布订阅模型,订阅者均能收到消息。消息队列,只有一个订阅者能收到消息。因此使用发布订阅还是消息队列,要搞清楚使用场景。
geo
geo是什么
GEO:存储经纬度,计算两地距离,范围计算等。
相关命令
API:geoadd key longitude latitude member # 增加地理位置信息
redis> geoadd cities:locations 116.28 39.55 bejing
(integer) 1
redis> geoadd cities:locations 117.12 39.08 tianjin 114.29 38.02 shijiazhuang 118.01 39.38 tangshan 115.29 38.51 baoding
(integer) 4
API:geopos key member [member...] # 获取地理位置信息
redis> geopos cities:locations tianjin
1)1) "117.12000042200088501"
2) "39.0800000535766543"
API:geodist key member1 member2 [unit] # 获取两位置距离,unit:m(米)、km(千米)、mi(英里)、ft(尺)
reids> geodist cities:locations tianjin beijing km
"89.2061"
API:
获取指定位置范围内的地理位置信息集合
georadius key longitude latitude radius m|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key] [storedist key]
georadiusbymember key member radius m|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key] [storedist key]
withcoord: 返回结果中包含经纬度
withdist: 返回结果中包含距离中心节点的距离
withhash: 返回结果中包含geohash
COUNT count:指定返回结果的数量
asc|desc:返回结果按照距离中心节点的距离做升序/降序
store key:将返回结果的地理位置信息保存到指定键
storedist key:将返回结果距离中心点的距离保存到指定键
redis> georadiusbymember cities:locations beijing 150 km
1)"beijing"
2) "tianjin"
3) "tangshan"
4) "baoding"
相关说明
- since redis3.2+
- redis geo是用zset实现的,type geokey = zset
- 没有删除API,可以使用zset的API:zrem key member
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。