第三章 小功能大用处
本章讲了很多redis的附加功能,这里只列出个人认为比较实用的功能
- 慢查询优化
- redis shell
- Pipeline
- 事务与Lua
- Bitmaps
- 发布订阅
3.1.慢查询优化
慢查询日志:
系统计算命令执行所耗费的时间,当这个时间超过了预设阈值,就将这条命令的信息写入慢查询日志中
一条客户端命令的生命周期为:
- 发送命令
- 命令排队
- 命令执行
- 返回结果
redis的慢查询机制只查询第三步前后耗费的时间,所以没有慢查询问题不代表没有超时问题
3.1.1.慢查询的两个参数配置
- 预设阈值:slowlog-log-slower-than(slowlog-max-len:说明了慢查询日志能存储多少条)
- 慢查询日志存放位置:存放在redis的一个列表里,如果日志条数超过slowlog-max-len则队头出队,队尾入队
修改参数配置
config set slowlog-log-slower-than xx
config set slowlog-max-len xx
config rewrite
获取慢查询日志
slowlog get [n] //虽然慢查询日志存放在redis中的一个列表中,但redis并没有暴露这个列表的key(n指定条数)
slowlog len //获取slowlog当前长度
slowlog reset //重置
慢查询日志 日志项属性
//伪代码标识
slowlog [
{
"标识id":"",
"发生时间戳":tiemstamp,
"命令耗时":timestamp,
"执行命令和参数":""
},
{
...
}
]
最佳实践
- slowlog-max-len:建议配置为1000以上
- slowlog-log-slower-than:默认值为10ms,对于高流量场景建议设置为1ms
3.2.reids shell
了解redis cli的一些重要参数
-
-r:重复命令,知道到达指定次数
$ redis-cli -r 3 ping PONG PONG PONG -
-i:每隔几秒执行一次命令,必须要和-r一起使用
redis-cli -r 5 -i 1 ping //每隔1秒执行一次,一共执行5次 PONG PONG PONG PONG PONG -
-x:从stdin读取数据作为redis-cli最后的参数
echo "world" | redis-cli -x set hello
3.3.Pipeline
RTT:往返时间
批量操作可以减少RTT,但并不是所有的数据结构都支持批量操作的,所以通过Pipeline技术将多条redis命令转换为一条命令,
将这条命令发给redis server,然后再将返回的结果依次返回给客户端,一般来说通过客户端来使用Pipeline.
3.4.事务与Lua
3.4.1.Redis中的事务
事务的概念不再重复,直接来看redis中的事务
multi //事务开始
exec //事务结束
discard //停止事务执行
在两条命令间执行的命令都不会真正的执行(返回QUEUED),而是保存在redis中,只有提交事务后才会真正得到执行
Redis事务的局限性:
- 命令错误:如果命令产生了语法错误,整个事务都无法执行
- 运行时错误:如果写错了命令(例如把sadd写成了zadd),提交事务时会发生错误,但redis不支持回滚,需要手动修改错误
3.4.2.Lua基本用法
数据类型:
booleans,numbers,strings,tables(表格)
local strings val="worlds"
local tables myArr={"redis",1,true}
local int sum=0;
for i=1,100
do
sum+=i
end
---数组长度
for i=1,#myArr
do
print(myArr[i])
end
---ipairs
for index,value in ipairs(myArr)
do
print(index)
print(value)
end
---while循环
while ...
do
...
end
---if else结构
if ...
then
...
else
...
end
---hash
local tables user_1={age=28,name="xiaoming"}
---function
fucntion funcName()
...
end
3.4.3.在Redis中使用Lua
-
eval
eval 'return "hello " .. KEYS[1] .. ARGV[1]' 1(key的个数) redis world如果脚本较长可以用redi-cli –eval直接执行文件
-
evalsha:将Lua脚本加载到redis server中,返回该脚本的sha校验和,通过校验和可以直接执行对于脚本,增加复用性
redis-cli script load "${cat lua_get.lua}" //加载脚本 evalsha {sha校验和} 1 redis world
Redis Api
redis.call("set","hello","world")
redis.call("get","hello")
3.4.3.案例
Lua脚本在redis中提供的好处:
- Lua脚本原子执行
- 定制命令
- 可以将多条命令打包,节省网络开支
lrange_and_incr.lua
local tables mylist=redis.call("lrange",KEYS[1],0,-1)
local int count=0
for index,value in ipairs(mylist)
do
redis.call("incr",key)
count++
end
return count
redis-cli --eval lrange_and_incr.lua hot:user:list
(integer) 5
3.4.4.Redis管理Lua脚本
-
script load
script load script -
script exists
script exists {sha1} -
script flush 清理Redis内存以及加载的Lua脚本
-
script kill 杀死当前执行的Lua脚本
3.5.Bitmaps
Bitmaps给予了开发者操作位的能力,可以简单理解为以位为单位的一个数组,数组每一项只能为0和1
-
设置值
setbit key offset value -
获取值
getbit key offset -
获取指定范围值为1的个数
bitcount key [start] [end] -
BitMaps间的运算
bitop op destkey key [key ...] //op:and or not xor实际案例
//计算出两天都访问过网站的用户数量 bit op and unique:users:and:{date1_date2} unique:users:and:{date1} unique:users:and:{date2} bitcount unique:users:and:{date1_datet2} -
计算BitMaps中第一个值为targetBit的偏移量
bitpos key targetBit [start] [end] bitops unique:users:{date} 1 //计算某一天访问网站的最小用户id(偏移量标识用户id,0和1表示是否登录)
3.7.发布订阅
-
发布消息
publish channel message publish channel:sports "XXXXXX" -
订阅消息
subscribe channel [channel ...] -
取消订阅
ubsubscribe [channel [channel ...]] punsubscribe [channel [channel ...]] //按照模式匹配取消订阅频道 -
查看订阅
pubsub channels [pattern] //查看活跃的频道,也就是当前频道至少有一个订阅者 pubsub numsub [channel ...] //查看频道订阅数 pubsub numpat //查看模式订阅数
发布订阅模式用于进行服务的解耦,比如某个数据发生了变化能及时的反馈给订阅该频道(该时间)的订阅者,然后做出对于响应