1. Redis功能—慢查询
1. 执行Redis命令的过程:
- 客户端向Redis发出命令
- 由Redis接收并将其该命令加入到命令队列中等待执行(单线程)
- 当轮到该命令时就会执行该命令
- 执行完成命令后就会返回执行结果。
所谓慢查询就是指在执行命令时发生的,客户端超时不一定是因为慢查询,但慢查询会引起客户端超时,上面四个步骤都有可能会引起客户端超时。
2. 慢查询:如果一条命令在上面过程中的第三步的执行时间超过规定时间,那么就会被判定为是一条慢查询,如果一条命令在第三步执行命令时被判定为是一个慢查询,该命令就会被放进一个先进先出的队列,而且该队列是一个固定长度的,而且该队列会被存储在内存中,当Redis关闭时,所有的慢查询命令都会被清空,换句话说,慢查询也是一类数据结构,其中的数据是一条条命令,示例结构如下图
3. 慢查询相关配置:
- slowlog-max-len:设置慢查询队列的长度,如果新加入一条命令使队列中命令总数量大于该数值就会将队列中的第一条推出去。
- slowlog-log-slower-than:设置判断某个命令为慢查询的时间阈值,单位是微秒,如果想要每条命令都进入慢查询队列,相当于记录每一条命令(可以获得每条命令的执行时间),那么就设置slowlog-log-slower-than=0,如果不想任何命令进入慢查询队列,就可以设置slowlog-log-slower-than<0即可,
4. 配置方法:slowlog-max-len和slowlog-log-slower-than都有默认值,分别是128和10000,通过命令config get slowlog-max-len和config get slowlog-log-slower-than即可获得相应的配置数值。
- 修改启动Redis的配置文件redis.conf,然后进行重启(不建议使用该方法,重启会丢失之前的慢查询队列数据,而且Redis尽量少重启)
- 通过命令动态配置慢查询配置参数,建议使用该方法,通过命令config set slowlog-max-len num和config set slowlog-log-slower-than num即可设置,比如config set slowlog-max-len 512和config set slowlog-log-slower-than 50000。
5. 相关命令:
- slowlog get [n]:获取慢查询队列,可选参数n表示获取前n条慢查询队列中的命令元素
- slowlog len:获取慢查询队列中的元素数量
- slowlog reset:清空慢查询队列
6. 慢查询运维经验:
- slowlog-log-slower-than:慢查询超时默认是10ms,但通常设置为1ms。
- slowlog-max-len:队列容量不能设置的过小
- 理解命令的执行过程
- 定期持久化慢查询,因为慢查询命令会逐渐增多,就会丢失之前的慢查询命令,所以要定期持久化之前的慢查询命令,比如存储到关系型数据库中,方便对系统中的一些异常进行对比排查。
2. Redis的功能—流水线(pipeline)
1. pipeline:即流水线运行命令功能,它指的是在客户端将一批命令打包,通过网络一次性发送给Redis进行执行,并将每条命令返回的处理结果也全部打包一次性返回给客户端。
2. 使用流水线功能对比不使用流水线功能的优点:客户端从发送命令到接收结果的时间消耗就只有一次网络发送和接收以及Redis处理计算这些命令的时间之和;而如果一条条命令的发送、接收结果和Redis中执行,那么无疑会多出很多在网络中传输所浪费的时间,造成一些不必要的时间浪费,所以pipeline功能就是为了解决该问题的。
非流水线执行批量命令:
通过流水线功能执行批量命令:
2. Jedis中使用pipeline功能的简单代码实例:
public class TestPipeline {
public static void main(String[] args) {
//创建一个Jedis对象,并连接到Redis服务器
Jedis jedis=new Jedis("192.168.10.128", 6379);
//获取一个流水线命令对象
Pipeline p=jedis.pipelined();
//添加100条set命令
for(int i=1;i<=100;i++){
p.set("id"+i, i+"");
}
//将这一批命令发送给Redis并等待执行返回结果
List<Object> list=p.syncAndReturnAll();
jedis.close();
}
}
3. 注意:流水线中的批量命令在通过网络传输至Redis后,会被拆开分成一个个的命令,这些命令不一定是和流水线中一样是连续的,因为它是每从流水线中分出一个命令,就添加到Redis的命令执行队列中取,在拆分的过程中就有可能有另一个命令插入到Redis的执行队列中去,所以流水线中批量命令在Redis中的执行不一定是连续的,但一定是按照流水线中存储的顺序执行的。
4. pipeline携带的命令数量并不是越多越好,一定要注意pipeline中所携带的命令数量并不能太多,太多依旧会影响传输速度,而且如果在集群环境中,一个pipeline只能作用于一个Redis节点。
3. Redis的功能—发布订阅
1. 发布订阅功能中的三个重要角色:发布者、订阅者和频道。发布者只负责向第三方(也就是频道)发送消息(比如杂志社把读者杂志交给邮局)。订阅者则被动接收消息(比如向邮局订阅读者杂志,门口去接邮过来的杂志)。第三方作用是则是相当于一个中转处,用于存储订阅杂志的接收方,并在杂志过来时送给接收方 (比如邮局)。
2. 相关的API命令:
- publish(向所有订阅者发布消息):publish channel message,该命令返回的是订阅者的数量,channel就表示频道,message就表示消息,比如 public show:tv "hello" ,就表示当前频道客户端向其他订阅者客户端发送消息
- subscribe(订阅某个频道):subscibe [channel],channel可以写一个或多个,该命令用于订阅该频道并接收这个channel中发布者客户端发布的消息
- unsubscribe(取消订阅某个频道):unsubscibe [channel],channel可以写一个或多个
- psubscribe(订阅某个频道):psubscibe [pattern],pattern类似于正则表达式,该命令用于订阅频道名能匹配pattern的所有频道,并接收这些channel中发布者客户端发布的消息
- punsubscribe(取消订阅):punsubscibe [pattern],pattern类似于正则表达式,该命令用于取消订阅频道名能匹配pattern的所有频道
3. 简单使用案例:
- 首先启动订阅者client订阅bar频道。格式:SUBSCRIBE name1 name2。 成功订阅回复,分别对应订阅类型、订阅频道、订阅数量。
redis-cli.exe -h 127.0.0.1 -p 6379
127.0.0.1:6379> SUBSCRIBE bar
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "bar"
3) (integer) 1
- 然后再新起个发布者client,发送消息。格式:publish channelName Message。
127.0.0.1:6380> publish bar val
(integer) 1
- 订阅client回复,分别对应消息类型,频道,消息。
1) "message"
2) "bar"
3) "val"
4. 消息队列功能:消息队列与发布订阅功能类似,但是消息队列中发布者发布消息后,并不是每一个订阅者都能取到消息,而是只有一个订阅者能够“抢”到发布者发布的消息,这也是消息队列与发布订阅的区别。
4. Redis的一种数据类型—Bitmap(位图)
1. key-value结构:key是普通的字符串,而value则是字符串数据类型的二进制码,所以,与其说bitmap是一种新的数据结构类型,不如说bitmap的命令是一种将string数据结构类型中的value转换为二进制码后,对二进制码的命令操作,对于string类型结构的key-vlaue数据,也可以使用该命令,不过会将将普通字符串转换为二进制码,然后才对指定下标上的二进制码进行读写操作。
2. 部分命令使用:
- setbit key offset vlaue:设置bitmap数据,offset表示在二进制码列表下标为offset的地方设为value值,value值只能为0或1,返回的是未设置新值之前的该下标处位置的二进制码(0或1),如果此前此下标处没有值,那么就返回0
- getbit key offset:获取value中,也就是二进制码列表中下标为offset的二进制码
- bitcount key [start end]:获取value中指定范围(下标从start到end)内二进制码为1的个数,如果不指定start和end,那就是在整个value中获取
- bitop op newkey key [key...]:op表示做多个value之间的交集(and)、并集(or)、非集(not)、异或(xor)操作,并将结果保存在newkey中,op处写and、or、not、xor。
- bitpos key targetbit [start] [end]:targetbit为二进制码,只能为0或1,表示获取value中指定范围内(从start到end,两个都不写表示在整个value范围,不写start表示从value开头到end,不写end表示从start到value末尾)找到的第一个等于targetbit的下标。
5. Redis的一种数据类型——hyperloglog
1. hyperloglog该数据结构类型并不是一个新的数据类型,而是基于HyperLogLog算法,以极小的空间完成独立数量统计,本质还是string类型的。
2. 专用命令:
- pfadd key element [element ...]:向hyperloglog添加元素,元素不重复
- pfcount key:计算hyperloglog的独立总数
- pfmerge newkey key [key...]:将多个key对应的hyperloglog进行合并,合并结果放到newkey中
3. hyperloglog的存在的问题:
- 具有错误率,也就是说每次pfcount key得到的数值不一定是对的
- 无法进行单条数据提取
所以在使用hyperloglog时,先要确定是否需要保证一定是正确的,其次是需要确定是否需要提取单条数据,然后再决定是否需要使用hyperloglog。
4. 使用hyperloglog的优点:以极少的内存消耗就能完成对大量数据的统计计数操作
6. Redis的功能——geo
1. geo(地理信息定位):存储经纬度,用于计算两地距离或者范围运算等,redis3.2版本之后才有的功能,其实际数据类型是zset,没有删除操作
2. 部分命令:
- geoadd key longitude latitude member [longitude latitude member ...]:添加一个geo 数据,longitude表示经度,latitude表示纬度,member表示该经纬度的标示,比如 geo key 116.28 39.55 beijing
- geopos key member [member ...]:获取经纬度信息
- geodist key member1 member2 [unit]:计算两地之间的距离,unit可以写 m(米)、km(千米)、mi(英里)、ft(尺)
- georadius key longitude latitude radius m|km|mi|ft [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key] [storedist key]:用于获取一个指定地点的指定范围内的地理信息集合,radius 表示指定范围数值;withcoord 表示返回的结果中包含经纬度;withdist 表示返回结果中包含距离中心位置的距离;withhash表示返回结果中包含geohash;COUNT count表示指定返回结果的数量;asc|desc表示按照距离中心位置的距离做升序或降序排序;store key表示将返回的地理位置信息保存到指定key中;storedist key表示将返回的地理位置距离中心位置的距离保存到指定key中