一:事物
事物的原理是先将一个事物的命令发送给redis,然后再让redis依次执行这些命令。
例如:
set foo 1
set foo2 3
multi
incrby foo 2
decrby foo2 2
exec
错误处理:
(1)语法错误:如果正确则加入事物队列,而只要有一个命令有语法错误就直接返回错误,连正确的命令也不会执行。(在版本2.6.5之前,版本会忽略语法错误的命令,然后执行事物中其他语法正确的命令)
(2)运行错误。运行错误是命令在执行时出现的错误,比如使用散列类型的命令操作集合类型的键,这种错误在实际执行之前redis是无法发现的,所以在事物里这样的命令会被Redis接收并执行。如果事物里面的一条命令出现了运行错误,事物里其他的命令依然会继续执行。
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> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
127.0.0.1:6379> getkey
(error) ERR unknown command `getkey`, with args beginning with:
127.0.0.1:6379> get key
"3"
127.0.0.1:6379>
运行后key的值是3,说明错误后的命令还是执行的。
二:过期时间
expire key seconds
其中,seconds参数表示键的过期时间,单位是秒。如果想知道一个键还有多就会被删除,使用如下命令:
ttl key
当键不存在时ttl命令会返回-2。没有为键设置过期时间,即永久存在的键会返回-1。
如果想要消除键的过期时间,使用:
persist key
如果过期时间被成功清除则返回1;否则返回0。
另外除了persist
,使用get
或者getset
命令为键赋值也同时会清除键的过期时间。如果想要更精确的设置过期时间使用pexpire key seconds
单位是毫秒。
三:SORT 命令
sort
命令可以对列表类型、集合类型、有序集合类型键进行排序,并且可以完成与关系数据库中的连接查询类似的任务。
127.0.0.1:6379> lpush mylist 4 2 6 1 3 7
(integer) 6
127.0.0.1:6379> get mylist
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> lrange mylist 0 -1
1) "7"
2) "3"
3) "1"
4) "6"
5) "2"
6) "4"
127.0.0.1:6379> sort mylist
1) "1"
2) "2"
3) "3"
4) "4"
5) "6"
6) "7"
除了排列数字外,sort命令还可以通过alpha参数实现按照字典顺序排列非数字元素,例如:
127.0.0.1:6379> del mylist
(integer) 1
127.0.0.1:6379> lpush mylist a c e d b c A
(integer) 7
127.0.0.1:6379> lrange mylist
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange mylist 0 -1
1) "A"
2) "c"
3) "b"
4) "d"
5) "e"
6) "c"
7) "a"
127.0.0.1:6379> sort mylist alpha
1) "a"
2) "A"
3) "b"
4) "c"
5) "c"
6) "d"
7) "e"
可以使用desc
实现倒叙排列。
四:by参数
By参数的语法是:BY 参考键
,其中参考键或者散列键的某个字段(表示为键名-> 字段名)。如果提供了BY参数,sort命令将不再依据元素自身的值进行排序,而是对每个元素的值替换参考键中的第一个*并获取其值,然后依据该值对元素排序:
例1:参考键是字符串类型
127.0.0.1:6379> lpush sortlist 2 1 3
(integer) 3
127.0.0.1:6379> lrange sortlist 0 -1
1) "3"
2) "1"
3) "2"
127.0.0.1:6379> set itemscore:1 50
OK
127.0.0.1:6379> set itemscore:2 100
OK
127.0.0.1:6379> set itemscore:3 -10
127.0.0.1:6379> sort sortlist by itemscore:* desc
1) "2"
2) "1"
3) "3
如果几个参考键值相同,则sort命令会再比较元素本身的值来决定元素的顺序。当某个元素的参考键不存在时,会默认参考键的值为0。
例2:参考键是散列类型
127.0.0.1:6379> lpush tag:ruby:posts 2 6 12 26
(integer) 4
127.0.0.1:6379> lrange tag:ruby:posts 0 -1
1) "26"
2) "12"
3) "6"
4) "2
127.0.0.1:6379> hset post:6 time 1352619600
(integer) 1
127.0.0.1:6379> hset post:2 time 1352619200
(integer) 0
127.0.0.1:6379> hset post:12 time 1352620100
(integer) 1
127.0.0.1:6379> hset post:26 time 1352620000
(integer) 1
127.0.0.1:6379> sort tag:ruby:posts by post:*->time desc
1) "12"
2) "26"
3) "6"
4) "2"
例3:参考键是常量(设置不存在的键),则不会进行排序
127.0.0.1:6379> lrange sortlist 0 -1
1) "4"
2) "3"
3) "1"
4) "2"
127.0.0.1:6379> sort sortlist by nothiskey
1) "4"
2) "3"
3) "1"
4) "2"
补充知识:如果参考键不存在,只要在最后的参考键加入*号,就能按照元素自身顺序排序。
例4:
127.0.0.1:6379> lrange sortlist 0 -1
1) "4"
2) "3"
3) "1"
4) "2"
127.0.0.1:6379> sort sortlist by somekey->somefiled:*
1) "1"
2) "2"
3) "3"
4) "4"
因为redis对每个元素都会读取somekey中的somefield:*字段,无论获得与否,每个元素的参考值是相同的,所以redis会按照元素本身的大小排序。
五:GET参数
get参数不影响排序,它的作用是使sort命令的返回结果不再是元素自身的值,而是get参数中指定的值。get和by参数一样,get参数也支持字符串类型和散列类型的键,并使用*作为占位符。例如要实现排序后返回ID对应的文章标题,可以这样写:
127.0.0.1:6379> sort tag:ruby:posts by post:*->time desc get post:*->title
1) "the natrue of ruby"
2) "Rethink -AN open source"
3) "uses for url"
4) "windows 8 app designs
要得到多个参数可以写多个get,get #会返回本身元素值
127.0.0.1:6379> sort tag:ruby:posts by post:*->time desc get post:*->title get post:*->time get #
1) "the natrue of ruby"
2) "1352620100"
3) "12"
4) "Rethink -AN open source"
5) "1352620000"
6) "26"
7) "uses for url"
8) "1352619600"
9) "6"
10) "windows 8 app designs"
11) "1352619200"
12) "2"
六 store 参数
默认情况下,sort命令会直接返回排序结果,如果希望保存排序结果,可以使用store参数,如果希望把结果保存在sort.result 键中:
127.0.0.1:6379> sort tag:ruby:posts by post:*->time desc get post:*->title get post:*->time get # store sort.result
(integer) 12
保存后的键的类型为列表类型,如果键已经存在则会覆盖它。加上sort参数命令的返回值为结果的个数。
性能优化:sort是redis 最强大、复杂的命令之一,如果实用不好也很容易成为性能瓶颈。sort的时间复杂度是O(n + mlog(m)),其中n为待排序元素的个数,m要返回的元素个数。要注意一下几点:
1)尽可能减少带排序键中元素数量(使N尽可能小)
2)使用limit参数只能获取需要的数据(使M尽可能小)
3)如果要排序的数据量较大,尽可能使用store参数将结果缓存。