一.事务

命令:multi…exec
multi后的命令,redis会把其存入事务队列,
当执行exec时,提交事务队列中的命令

错误处理
1.语法错误:命令不存在或命令参数个数不对例:

127.0.0.1:6379> multi
 OK
 127.0.0.1:6379> set key 23
 QUEUED
 127.0.0.1:6379> set key
 (error) ERR wrong number of arguments for ‘set’ command
 127.0.0.1:6379> exec
 (error) EXECABORT Transaction discarded because of previous errors.

结果:全部命令都不会执行

2.运行错误:命令在执行时出错(如用散列类型的命令操作集合类型的键)
例:

127.0.0.1:6379> multi
 OK
 127.0.0.1:6379> set key 1
 QUEUED
 127.0.0.1:6379> sadd key 2
 QUEUED
 127.0.0.1:6379> set key 3
 QUEUED
 127.0.0.1:6379> exec1. OK
2. (error) WRONGTYPE Operation against a key holding the wrong kind of value
3. OK
 127.0.0.1:6379> get key
 “3”

结果:如何事务里一条命令运行错误,别的命令依旧继续执行,因为redis事务没有关系数据库事务
提供的回滚功能,因此开发要在执行出错后还原数据。其实如果能规划好key的命名规则,上面的
问题基本不会出现

watch命令:要以监控一个或多个键,一旦其中一个键被修改了,之后的事务不会被执行,
会一直监控到exec命令结束,所以注意watch后没有事务,要有unwatch命令来保证下一个事务不受影响
例子:

127.0.0.1:6379> get key
 “3”
 127.0.0.1:6379> set key 1
 OK
 127.0.0.1:6379> watch key
 OK
 127.0.0.1:6379> set key 2
 OK
 127.0.0.1:6379> multi
 OK
 127.0.0.1:6379> set key 3
 QUEUED
 127.0.0.1:6379> exec
 (nil)
 127.0.0.1:6379> get key
 “2”

二.生存时间

命令:设置过期时间
expire key sec/pexpire key 毫秒
expireat unix时间/pexpireat unix时间

查看还有多久过期(-1代表不存在):ttl key

取消键的生存时间(persist,set或getset也会消除键的生存时间):persist key

注意:incr,lpush,hset,zren不会影响键的生存时间

用处:
1.实现访问频率限制————限制用户每分钟最多只能访问10个页面
使用一个列表类型的键来记录他最近10次访问的时间,键超过10个就判断最早的元素到现在是否大于一分钟,
如果大于,就提示用户一会再来访问并删除此元素,否则添加此元素
2.实现缓存————session存储和过期

redis内存清理策略
配置:
maxmemory:redis最大可用内存
maxmemory-policy:删除策略(推荐使用LRU least recently used)
当内存超过maxmemory时,会执行maxmemory-policy策略

redis支持的内容清理策略规则

redis 数据 根据时间 排序查询 redis按时间排序_事务

三.排序

命令(ALPHA参数可实现对非数据排序):
sort key [BY pattern] [LIMIT offset count] [GET paern …][ASC DESC][ALPHA]
作用
1.对列表,集合,有序集合进行排序(有序集合只对自身值排序)
例子

127.0.0.1:6379> lrange list 0 9
1. “78”
2. “45”
3. “67”
4. “34”
5. “12”
6. “5”
7. “4”
8. “2”
9. “1”
 127.0.0.1:6379> sort list10. “1”
11. “2”
12. “4”
13. “5”
14. “12”
15. “34”
16. “45”
17. “67”
18. “78”
 127.0.0.1:6379> sort list limit 0 319. “1”
20. “2”
21. “4”

2.可以实现关系数据 库中的连接查询(stu集合放学生学号,stu:* 用来记录学生成绩,取成绩最好的三个学生的学号)
例子

127.0.0.1:6379> lpush stu 1 2 3 4
 (integer) 4
 127.0.0.1:6379> set stu:1 98
 OK
 127.0.0.1:6379> set stu:2 78
 OK
 127.0.0.1:6379> set stu:3 89
 OK
 127.0.0.1:6379> set stu:4 99
 OK
 127.0.0.1:6379> sort stu by set:* desc limit 0 31. “4”
2. “3”
3. “2”

3.在2的基础上,返回想要的字段(按学生的年龄排序并显示学生的名称)

127.0.0.1:6379> hmset student id 1 name aa age 18
 OK
 127.0.0.1:6379> hmset student:1 id 1 name aa age 18
 OK
 127.0.0.1:6379> hmset student:2 id 2 name bb age 34
 OK
 127.0.0.1:6379> hmset student:3 id 3 name cc age 23
 OK
 127.0.0.1:6379> hmset student:4 id 4 name dd age 12
 OK
 127.0.0.1:6379> sort stu by student:*->age desc1. “2”
2. “3”
3. “1”
4. “4”
 127.0.0.1:6379> sort stu by student:->age desc get student:->name5. “bb”
6. “cc”
7. “aa”
8. “dd”
 127.0.0.1:6379> sort stu by student:->age desc get student:->name get #9. “bb”
10. “2”
11. “cc”
12. “3”
13. “aa”
14. “1”
15. “dd”
16. “4”


4.保存结果store,常跟expire一起使用:
127.0.0.1:6379> sort stu by student:->age desc get student: store sort.result
(integer) 4

性能优化:
sort的时间复杂度(n+mlogm)
1.尽可能减少待排序键中元素的数据(n尽可能小)
2.使用limit获取需要数据(m尽可能小)
3.排序数量大,尽可能使用store参数将结果缓存。

四.消息通知

生产者将需要处理的任务放在任务队列,
而消费者则不断从任务队列中拉取任务信息并执行。

使用列表来实现任务队列
生产者将任务使用lpush加入到某个键中,
消费者使用rpop从该键中取出任务(可以使用brpop来优化,它会阻塞连接,直到有新元素加入)。

例子(实际都是放在循环中,此处只是说明下语法作用):
redisA> brpop queue 0

redisB> lpush queue task1
(integer) 1

redisA的结果:

  1. “queue”
  2. “task1”
    (21.19s)

进阶:优先级队列
blpop queue:1 queue:2 0,例子(实际都是放在循环中,此处只是说明下语法作用):
redisA> blpop queue:1 queue:2 0

redisB> lpush queue:2 task
(integer) 1

redisA的结果:

  1. “queue:2”
  2. “task”
    (16.32s)

"发布/订阅"模式:类似上面,这里只说下语法
publish channel message
subscribe channel
subscribe命令执行后客户端会进入订阅状态 ,只能使用subscribe/unsubscribe等命令,
别的命令无法执行

Redis A> subscribe channel.1
 Reading messages… (press Ctrl-C to quit)1. “subscribe”
2. “channel.1”
3. (integer) 1
Redis B> publish channel.1 h
 (integer) 1Redis A的结果:
1. “message”
2. “channel.1”
3. “h”

五.管道

客户端与redis使用TCP协议进行连接,命令的发送及结果的返回都需要经过网络传输,这部分总耗时称为往返时延。
redis的底层通信协议对管道提供了支持,通过管道可以一次性发送多条命令并在执行完成后一次性将结果返回(命令间不相互依赖时),
以此达到降低往返时延累计值。