Redis(二) 小功能

Posted by ZhouJ000 on November 1, 2018
最后更新于:2018-11-03

Redis(一) 基础与api
Redis(二) 小功能
Redis(三) 阻塞与内存
Redis(四) 缓存设计
Redis(五) 客户端调用
Redis(六) 持久化与复制
Redis(七) 哨兵
Redis(八) 集群

慢查询分析

redis执行一条命令分为4个部分:
1、发送命令
2、命令排队
3、命令执行
4、返回结果
慢查询只统计第3步,所以没有慢查询不代表客户端没有超时问题

1、预设阀值: slowlog-log-slower-than,单位是微秒,默认值是10000。假如执行了一条命令它的执行时间超过10000微秒,就会被记录在慢查询日志中
2、存放日志: redis使用一个列表来存储慢查询日志,slowlog-max-len设置列表的最大长度。当新日志插入列表已处于最大长度时,最早插入的命令将从列表中移出
3、修改配置: 一种是修改配置文件,另一种是使用config set命令动态修改(config rewrite持久化到本地配置)
4、慢日志查询: slowlog get [n]
5、慢日志长度: slowlog len
6、慢日志重置: slowlog reset

最佳实践

1、slowlog-max-len线上可以设置大一点,例如设置为1000以上。记录慢查询时redis会对长命令做截断处理,不会占用大量内存;而且可以减缓慢查询被剔除的可能
2、slowlog-log-slower-than默认设为10毫秒来判断。由于redis采用单线程响应命令,对于高流量场景,如果命令执行时间在1毫秒以上,那么redis最多可支持OPS不到1000。因此对高OPS场景的redis建议设置为1毫秒
3、慢查询只记录命令执行时间,并不包括命令排队和网络传输时间。因此客户端执行命令的时间会大于命令的实际执行时间。因为命令执行慢查询机制,慢查询会导致其他命令级联阻塞,因此当客户端出现请求超时,需要检查该时间点是否有对应的慢查询,从而分析出是否为慢查询导致的命令级联阻塞
4、由于慢查询日志是先进先出队列,所以在慢查询较多时,可能会丢失部分慢查询命令,所以需要定期执行slow get命令将慢查询日志持久化到其他存储中,然后通过制作可视化界面进行查询

Redis Shell

redis-cli
-r,代表命令执行多次,如 redis-cli -r 3 ping
-i,代表每隔几秒执行一次命令
-x,代表从标准输入读取数据作为redis-cli的最后一个参数
-c,连接redis cluster节点时使用
-a,如果配置了密码,不需要手动输入auth命令
–scan/–pattern: 用于扫描指定模式的键
–slave,把当前客户端模拟成当前redis节点的从节点,可以用来获取当前redis节点的更新操作
–rdb,请求redis实例生成并发送RDB持久化文件保存在本地,可用作持久化文件的定期备份
–pipe,将命令封装成redis通信协议定义的数据格式,批量发送给redis执行
–bigkeys,使用scan命令对redis的键进行采样,从中找到内存占用比较大的键,这些可能是系统的瓶颈
–eval,执行指定lua脚本
–latency/–latency-history/–latency-dist,检测网络延迟
–stat,实时获取redis的重要统计信息,虽然info命令更全,但可以实时看到增量数据

redis-server
除了启动redis外,还有个–test-memory选项。用来检测当前操作系统能否稳定的分配指定容量的内存给redis,可以检测避免因内存问题导致redis崩溃

redis-benchmark:可以为redis做基准测试
-c,代表客户端并发数(默认50)
-n,代表客户端请求总量(默认100000),例如redis-benchmark -c 100 -n 20000
-t,对指定命令做基准测试,例如redis-benchmark -t get,set -q

Pipeline

在redis执行命令的4个过程中,1发送命令和4返回结果称为RTT,往返时间。redis提供了批量操作来节省PTT,但大部分命令是不支持批量操作的。Pipeline机制能改善这类问题。它能将一组redis进行组装,通过一次PTT传输给redis,再将这组redis命令的执行结果按顺序返回给客户端

redis-cli的–pipe选项就是使用Pipeline机制

原生批量操作与Pipeline对比:
1、原生批量操作是原子的,Pipeline是非原子的
2、原生批量操作是一个命令对应多个key,Pipeline支持多命令
3、原生批量操作是redis服务端支持实现的,而Pipeline需要服务端和客户端的共同实现

事务与lua

redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。multi命令代表事务开始,exec命令代表事务结束,它们之间的命令是原子顺序执行的。如果要停止事务执行,可以使用discard命令代替exec命令。在执行中,如果命令语法错误,导致整个事务无法执行;如果运行时错误,但语法正确,redis并不支持回滚功能。有些场景需要保证事务中key不被其他客户端修改,如果被改过就不执行,可以使用watch命令来解决这个问题

redis执行lua脚本有2种方法,eval和evalsha
lua脚本在redis中是原子执行的,执行过程不会插入其他命令。还可以帮助开发和运维定制自己的命令,并可以将其常驻在redis内存中实现复用。lua脚本还可以将多条命令一次性打包,有效减少网络开销

redis管理lua脚本:
1、script load script 将lua脚本加载到内存中
2、scripte exists sha1 [sha1…] 判断sha1是否已经加载到redis内存中
3、script flush 清除redis内存已加载的所有lua脚本
4、script kill 杀掉正在执行的lua脚本

Bitmaps

redis提供Bitmaps这个”数据结构”,可以实现对位的操作。但是Bitmaps本身不是一种数据结构,实际上是字符串,但是可以对字符串的位进行操作;Bitmaps单独提供了一套命令,所以在redis中使用与字符串不同

1、设置值: setbit key offset value
2、获取值: gitbit key offset
3、获取指定范围值为1的个数: bitcount [start] [end]
4、运算: bitop op destkey key [key…] (and交集 or并集 not非 xor异或)
5、计算Bitmaps中第一个值为targetBit的偏移量: bitpos key targetBit [start] [end]

使用案例: 比如在每天独立用户访问量很大的场景进行统计

HyperLogLog

是一种基数算法。通过HyperLogLog可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等

1、添加: pfadd key element [element…]
2、计算独立用户数: pfcount key [key…]
3、合并: pfmerge destkey sourcekey [sourcekey…]

实践注意:
1、HyperLogLog内存占用量很小,但是存在错误率
2、只为了计算独立总数,不需要获取单条数据时使用
3、可以容忍一定误差率,毕竟在内存占用量上有很大的优势

发布订阅

redis提供了基于发布/订阅模式的消息机制。此模式下,发布者和订阅者不进行直接通信,发布者向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息

1、发布消息: publish channel message
2、订阅消息: subscribe channel [channel…]
3、取消订阅: unsubscribe channel [channel…]
4、按模式订阅和取消订阅: psubscribe、punsubscribe
5、查看活跃的频道: pubsub channels [pattern]
6、查看频道订阅数: pubsub numsub [channel…]

使用场景:聊天室、公告牌、服务间利用消息解耦

GEO

地理定位功能

1、添加地理位置信息: geoadd key longitude latitude member [longitude latitude member …]
2、获取地理位置信息: geopos key member [member…]
3、获取两个地理位置的距离: geodist key member1 member2 [unit]
4、获取指定位置范围内的地理信息位置集合: georadius、georadiusbymember
5、获取geohash: geohash key member [member…]
6、删除地理位置信息: zrem key member (GEO没有提供删除成员命令,因为GEO底层实现是zset,所以可以借助zrem命令实现删除)