redis 慢查询
redis 查询的生命周期:
redis 慢查询:
- 慢查询发生在 redis 查询周期的第三阶段,一般指耗时较长的操作,如 key * 等需要进行全表扫描的操作
- 客户端超时不一定是慢查询,但慢查询是客户端超时的一个可能因素
两个配置参数:
- slowlog-max-len:慢查询队列是一个保存在内存中的固定长度的先进先出队列,该参数指定该队列的长度,默认值 128
- slowlog-log-slower-than:慢查询阈值(单位:微秒),默认值 10000 微秒(1ms = 1000 微秒)
- slowlog-log-slower-than = 0,记录所有命令
- slowlog-log-slower-than < 0,不记录任何命令
配置方法:
- 查看默认值:config get 配置参数名
- 修改配置值:
- 静态:修改 redis.conf 并重启
- 动态:config set 配置参数名 配置参数,如 config set slowlog-log-slower-than 1000
慢查询命令:
- slowlog get [n]:获取慢查询队列
- slowlog len:获取慢查询队列长度
- slowlog reset:清空慢查询队列
使用经验:
- slowlog-max-len不要设置过大,默认10ms,通常设置1ms
- slowlog-log-slower-than不要设置过小,通常设置 1000 左右
- 理解命令生命周期
- 定期持久化慢查询
Pipeline
一次网络命令通信模型:
批量网络命令通信模型:
流水线 Pipeline:
- redis 命令时间是微妙级别
- pipeline 每次条数需要控制(网络)
// 1.创建JedisPool
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(10);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "47.113.89.216", 6379);
// 2.使用pipeline
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
// 使用pipeline
for (int i = 0; i < 100; i++) {
Pipeline pipeline = jedis.pipelined();
for (int j = i * 100; j < (i + 1) * 100; j++) {
pipeline.hset("hashkey:" + j, "field" + j, "value" + j);
}
pipeline.syncAndReturnAll();
}
} finally {
if (jedis != null) {
jedis.close();
}
}
Pipeline 使用建议:
- 注意每次 pipeline 携带数据量
- pipeline 每次只能作用在一个 Redis 节点上
- M 操作与 pipeline 的区别:
- M 操作是原子操作,如 mset、mget
- pipeline 不是原子操作
发布订阅
角色:
- 发布者(publisher)
- 订阅者(subscriber):支持订阅多个频道
- 频道(channel)
发布订阅模型:
消息队列模型:
相关 API:
1、publisher 发布命令:publish channel message
2、subscriber 订阅:
- 订阅一或多个频道:subscribe [channel , …]
- 取消订阅:unsubscribe [channel , …]
- 根据模式匹配进行订阅:psubscribe [pattern , …]
- 退订指定的模式:punsubscribe [pattern , …]
- 列出至少有一个订阅者的频道:pubsub channels
- 列出给定频道的订阅者数量:pubsub numsub [channel , …]
- 列出被订阅模式的数量:pubsub numpat
Bitmap
redis 提供了针对 bit 的操作,相关 API 如下:
1、给位图指定索引设置值:setbit key offset value
- key:键值
- offset:位的索引
- value:bit 的值
2、获取位图指定索引的值:getbit key value
3、获取位图指定范围位值为 1 的个数:bitcount key [start] [end]
- 范围为 start - end,单位为字节
- 如果不指定范围则获取全部
4、将多个 bitmap 进行 op 操作并将结果保存在的 destkey 中:bitop op destkey [ key , … ]
- op 为位操作类型: and(交集)、or(并集)、not(非)、xor(异或)
5、计算位图指定范围第一个偏移量对应的值等于 targetBit 的位置:bitops key targetBit [start] [end]
- start - end,单位为字节,如果不指定则获取全部
使用建议:
- type=string,最大为512MB
- 注意setbit时的偏移量,可能有较大耗时
- 位图不是绝对好
HyperLogLog
基于 HyperLogLog 算法:极小空间完成独立数据统计,本质是字符串
- type hyperloglogkey=string
常用API:
命令 | 含义 |
---|---|
pfadd key [element , … ] | 向 hyperloglog 添加元素 |
pfcount [key , … ] | 计算 hyperloglog 的独立总数 |
pfmerge destkey [sourcekey , … ] | 合并多个 hyperloglog |
使用:
127.0.0.1:6379> pfadd user:high user:01 user:02 user:03
(integer) 1
127.0.0.1:6379> pfadd user:high user:01 user:04
(integer) 1
127.0.0.1:6379> pfcount user:high
(integer) 4
127.0.0.1:6379> pfadd user:low user:07 user:08
(integer) 1
127.0.0.1:6379> pfcount user:low
(integer) 2
127.0.0.1:6379> pfadd user:rich user:01 user:08
(integer) 1
127.0.0.1:6379> pfmerge user:richhigh user:rich user:high
OK
127.0.0.1:6379> pfcount user:richhigh
(integer) 5
127.0.0.1:6379> type user:rich
string
使用经验:
- 是否能容忍错误:错误率 0.81%
- 是否需要单条数据
GEO
GEO:地理信息定位,存储经纬度,计算两地距离,范围计算等
- since 3.2+
- type geoKey=zset
GEO 的 API:
命令 | 含义 |
---|---|
geoadd key [ longitude latitude member , … ] | 增加地理位置信息,longitude经度,latitude纬度 |
geopos key [ member , … ] | 获取地理位置信息 |
geodist key member1 member2 [unit] | 获取两个地理位置的距离,unit:m(米)、km(千米)、mi(英里)、ft(尺) |
复杂API:
127.0.0.1:6379> geoadd china 116.28 38.55 beijing
(integer) 1
127.0.0.1:6379> geoadd china 117.12 39.08 tianjin
(integer) 1
127.0.0.1:6379> geoadd china 114.29 38.02 shijiazhuang
(integer) 1
127.0.0.1:6379> geopos china shijiazhuang
1) 1) "114.29000169038772583"
2) "38.01999994251037407"
127.0.0.1:6379> geodist china shijiazhuang beijing km
"183.4623"
127.0.0.1:6379> type china
zset