redis之(九)redis的事务机制
[一]什么是redis的事务
--->redis的事务是一组命令的集合。
--->redis的事务是保证一组命令,要么都执行,要么都不执行。但不支持一组命令中,其中一个或多个执行失败,不支持数据回滚。数据的一致性,由程序员控制。
--->redis的事务还能保证一个事务内的命令依次执行,而不被其他命令插入。试想,客户端 A发送几条命令到redis服务器,客户端B也送了一条命令也到redis服务器上。如果不使用事务,则客户端 B的那条命令就有可能在客户端A的那几条命令中间执行。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务。
- 命令入队。
- 执行事务。
序号 | 命令及描述 |
---|---|
1 | DISCARD 取消事务,放弃执行事务块内的所有命令。 |
2 | EXEC 执行所有事务块内的命令。 |
3 | MULTI 标记一个事务块的开始。 |
4 | UNWATCH 取消 WATCH 命令对所有 key 的监视。 |
5 | WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 |
[二]redis事务大白话
--->利用MULTI开启事务,然后发送一组命令。在利用EXEC去依次执行这一组命令。
--->redis的事务说白了就是,有一个收集器,从客户端接受一组命令,然后一起执行。如果客户端在发送exec前断连,则那组命令是不会被执行的。这就是redis的事务。如下图。
[三]redis事务的错误处理
--->如果一个事务中的某个命令执行出错,redis会怎么处理。2.65版本以后。
(1)第一种:命令语法错误。语法错误是指命令不存在活着命令的参数的个数不对。
处理:如果一组命令中有语法错误的,则所有命令都不会执行。包括那些语法正确的命令。
(2)第二种:运行错误,是指在命令执行时出现错误。比如:散列类型的命令,操作集合类型的键。
处理:正确的命令会执行,运行错误的命令不会被执行,已经执行的命令的数据也不会回滚。需要程序员自己在代码中实现回滚。
[四]WATCH命令
--->WATCH key
--->该命令会监控某个键。其他客户端和当前客户端对该键的值不做修改,那么当前的客户端接下来提出的事务对该键值的操作就可以执行。否则,当前客户端提出的事务中所有的命令不被执行。
--->一旦执行exec后,当前客户端对键的监控就会失效。
--->例子:A客户端在时间点a监控了x键,B客户端或者A客户端在时间点b(b在a之后)对x键的值做了修改。同时,A客户端用MULTI提出一个事务,发送了一组命名。那么改组命令,在等到A客户端发送EXEC去执行整组命令的时候,该组所有的命令不会被执行。如下图模拟。
[五]UNWATCH命令
--->unwatch命令可以取消对所有key键的监控。从而不会因为在事务提交执行时,因为监控后,事务声明前有客户端对键做了修改,而阻止事务执行。
[六]过期时间
--->命令:EXPIRE key seconds (单位。秒。必须整数)
--->让某个键在redis服务器上存活seconds秒后,自动删除。
--->设置成功返回:1,设置失败或键不存在返回:0
--->命令:PEXPIRE key millisecond(单位。毫秒。必须是整数)
--->让某个键在redis服务器上存活 millisecond毫秒后,自动删除
--->命令:TTL key
---> 查看某个key还有多长时间被自动删除
--->如果是永久键,返回-1.如果键不存在返回-2,如果是设置了失效的时间的键返回剩余多少秒就失效的秒数。
--->命令:PERSIST key
--->如果想把设置了失效时间的键,变成永久键。则用该命令。
--->如果过期时间被清除返回1,否则返回0(因为键不存在,或是键本来就是永久的)
&&注意点:如果使用watch命令检测一个拥有过期时间的键,该键时间到期自动删除并不回被watch命令认为该键被改变
[七]排序 (排序对象,集合,有序集合,列表)
---> 命令:SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ....]] [ASC|DESC] [ALPHA] [STORE destination]
--->该命令可以对列表类型,集合类型和有序集合类型键进行排序。
--->该命令还可以完成与关系数据库中的连接查询相类似的任务
--->sort是redis中最强大,最复杂的命令之一。如果使用不好会造成性能瓶颈。
--->sort命令的时间复杂度是0(n+mlog(m)),其中,n表示要排序的列表(集合或有序集合)中的元素个数,m表示要返回的元素个数。当n较大的时候sort的命令性能越低,并且redis在排序前会建立一个长度为n的容器来存储待排序的元素,虽然是一个临时过程,但如果同时进行较多的大数据量的排序操作则会严重影响性能
--->开发中使用sort命令时需要注意以下几点
1.尽可能减少待排序键中的元素数量(使n尽可能小)
2,使用limit参数只获取需要的数据(使m尽可能小)
3,如果要排序的数据量较大,尽可能使用store参数将结果缓存
&例外:当要排序的键类型为有序集合且参考键为常量键名时候容器大小为m,而不是n
(1)对列表类型的数据进行排序
(2)对有序集合类型排序会忽略元素的分数,值针对元素自身进行排
(3)SORT命令除了可以排序数字外,还可以通过ALPHA参数实现按照字典顺序排列非数字元素。如果是非数字元素需要排序,没有加ALPHA则会报错
(4)BY 参数:语法:BY 参考键。
-->参考键,可以是字符串类型的键,或者是散列类型的某个字段(表示为:键名->字段名)
-->* 表示匹配集合中的元素。如例子中的post:*。匹配所有post:1,post:2,post:3
-->当参考键名不包含*时(即常量键名),与要排序的键中的元素值无关。sort命令将不会执行排序操作。因为redis认为这种情况是没有意义的。也没有执行排序操作。
-->但是在不需要排序,但需要借助sort命令获得与元素相关联的数据时,常量键名很有用。
-->参考键虽然支持散列类型,但是*只能在->的前边(即键名的部分)才有用。在->后(即字段的部分)会被当成字段名本身而不会被理解成占位符,从而被元素替换。即常量键名。所以redis是按照要排序元素的本身进行排序,而不是按照参考键名对要排序的元素进行排序。
(5)GET参数 语法:GET 匹配表达式
--->其不影响排序结果
--->而是从排序结果中,按表达式匹配,返回符合表达式的结果集合。
--->表达式,和by参数的参考键名规则一样,支持字符串和散列类型的键。并使用*作占位符号。
(6)STORE 参数 语法:STORE 键名
-->默认情况下SORT会直接返回排序结果,如果希望保存排序结果。可以使用STORE参数。
-->保存后的键为列表类型的。如果键已经存在则覆盖它
-->排序命令加上store的时候,返回的结果是保存在结果键里的元素个数。