127.0.0.1:6379> multi
OK
127.0.0.1:6379> srem number 1
QUEUED
127.0.0.1:6379> srem number 3
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
事务的错误处理
1语法错误比如参数个数错误:全部不执行
2.运行错误比如用lpush 操作set类型:正确的执行,错误的不执行
watch:
Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
WATCH key [key …]
127.0.0.1:6379> watch number
OK
127.0.0.1:6379> sadd number 2 3 3
(integer) 1
127.0.0.1:6379> nulti
(error) ERR unknown command `nulti`, with args beginning with:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> srem number 2
QUEUED
127.0.0.1:6379> exec
(nil)
过期时间:没有设置的ttl返回-1 , 设置后被删除的返回-2,过期的建不会被watch检测到
127.0.0.1:6379> set k lalala
OK
127.0.0.1:6379> expire k 10
(integer) 1
127.0.0.1:6379> ttl k
(integer) 7
127.0.0.1:6379> ttl k
(integer) 5
127.0.0.1:6379> persist k //取消expire设置,使用set或者get等赋值操作也可以取消,重新调用expire会重置时间
p使用毫秒为单位
expireat 和 pexpireat使用unix时间作文参数
如果redis配置了maxmemory和maxmemory-policy策略,则当redis内存数据达到maxmemory时,会根据maxmemory-policy配置来淘汰内存数据,以避免OOM。
redis提供了以下6种淘汰策略:
1,noeviction:不执行任何淘汰策略,当达到内存限制的时候客户端执行命令会报错。
2,allkeys-lru:从所有数据范围内查找到最近最少使用的数据进行淘汰,直到有足够的内存来存放新数据。
3,volatile-lru:从所有的最近最少访问数据范围内查找设置到过期时间的数据进行淘汰,如果查找不到数据,则回退到noeviction。
4,allkeys-random:从所有数据范围内随机选择key进行删除。
5,volatile-random:从设置了过期时间的数据范围内随机选择key进行删除。
6,volatile-ttl:从设置了过期时间的数据范围内优先选择设置了TTL的key进行删除。
z* 有序集合可以实现
SORT命令:
127.0.0.1:6379> lpush k 5 4 2 1 3
(integer) 5
127.0.0.1:6379> sort k //正序
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> sort k desc//倒叙
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> sort k desc limit 1 2 //limit offset count操作
1) "4"
2) "3"
By参数:
sort
3) [BY pattern] (set)
除了可以按集合元素自身值(数字,字母)排序外,还可以将集合元素内容按照给定pattern组合成新的key,并按照新key中对应的内容进行排序。
示例:
代码如下:
127.0.0.1:6379> set mimvp_12 mimvp_12
OK
127.0.0.1:6379> set mimvp_11 mimvp_11
OK
127.0.0.1:6379> set mimvp_13 mimvp_13
OK
127.0.0.1:6379> set mimvp_10 mimvp_10
OK
127.0.0.1:6379> sort mimvp by mimvp_* // mimvp_* 是字符串,因此需要alpha
(error) ERR One or more scores can't be converted into double
127.0.0.1:6379> sort mimvp by mimvp_* alpha
1) “10”
2) “11”
3) “12”
4) “13”
127.0.0.1:6379> sort mimvp by mimvp_* alpha desc
1) “13”
2) “12”
3) “11”
4) “10”
127.0.0.1:6379> hset user_12 name yanggang
(integer) 1
127.0.0.1:6379> hset user_11 name yangjie
(integer) 1
127.0.0.1:6379> hset user_13 name yangliang
(integer) 1
127.0.0.1:6379> hset user_10 name yangchuang
(integer) 1
127.0.0.1:6379> sort result get user_*->name
(empty list or set)
127.0.0.1:6379> lpush mimvp 12
(integer) 1
127.0.0.1:6379> lpush mimvp 11
(integer) 2
127.0.0.1:6379> lpush mimvp 13
(integer) 3
127.0.0.1:6379> lpush mimvp 10
(integer) 4
127.0.0.1:6379> sort mimvp by user_*->name get user_*->name alpha // 按照user_*->name的大小排序并获取user_*name
1) "yangchuang"
2) "yanggang"
3) "yangjie"
4) "yangliang"
127.0.0.1:6379> sort mimvp by user_*->name get user_* alpha
1) (nil)
2) (nil)
3) (nil)
4) (nil)
127.0.0.1:6379> sort mimvp by user_*->name alpha// 按照user_*->name的大小排序并获取minvp中的原始值
1) "10"
2) "12"
3) "11"
4) "13"
127.0.0.1:6379> sort mimvp by user_*->name get user_*->name alpha store res//store 存储进一个列表类型
(integer) 4
127.0.0.1:6379> lrange res
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange res 0 -1
1) "yangchuang"
2) "yanggang"
3) "yangjie"
4) "yangliang"
任务队列:松耦合 易于拓展
127.0.0.1:6379> lpush queue 1 2 3 //
(integer) 3
brpop和blpop类似
127.0.0.1:6379> brpop queue 0 // brpop会在得到元素前一直阻塞
1) "queue"
2) "1"
(16.84s)
127.0.0.1:6379> brpop queue 0
1) "queue"
2) "2"
127.0.0.1:6379> brpop queue 0
1) "queue"
2) "3"
优先队列:
brpop可以同时检测多个键 从左往右优先级递减
127.0.0.1:6379> lpush key1 1 2 3
(integer) 3
127.0.0.1:6379> lpush key2 4 5 6
(integer) 3
127.0.0.1:6379> brpop key2 key1 0
1) "key2"
2) "4"
发布/订阅模式:
publish / subscribe 支持按照glob 正则*?订阅 , unsubscribe取消订阅
127.0.0.1:6379> subscribe channel1 channel2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "subscribe"
2) "channel2"
3) (integer) 2
127.0.0.1:6379> publish channel1 lalaal
(integer) 1
127.0.0.1:6379> publish channel2 lalaal
(integer) 1
1) "message"
2) "channel1"
3) "lalaal"
1) "message"
2) "channel2"
3) "lalaal"
当较晚的redis操作不依赖之前的操作的时候可以使用管道加快速度,因为默认是顺序执行的
1精简键名
2内部编码优化:
127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> object encoding foo
"embstr"
127.0.0.1:6379>
redis每个键都有相同的内部结构体
1. 字符串
redisobject的void指针指向一个
struct sdshdr{
int len//长度
int free//剩余空间
char buf[];
}
所以创建一个字符串类型所需要的空间是sizeof(rsdisobject)+sizeof(sds)+sizeof(内容)
当可以转化为数字时会用long存储,所需空间位sizeof(redisobject)
refcount代表了被引用次数,redis如果没有设置maxmemory的话(如果设置可能会被lru清楚,所以直接不设置)会在启动时创建0-9999的数字redisobject,这样新的数字创建时直接指向预创建的对象就可以,不用开辟空间
embstr编码将redisobject和sdshdr分配在同一连续内存块上,开辟和释放都减少一次,修改时自动切回raw模式
2.散列类型
有HT和ZIPLIST
ZIPLIST:键个数和每个字段名字段值都长度小于 设定值entry 和 value时
zip紧凑
HT:其他
3.列表类型
Linkedlist和zip
新的quicklist 是将一个列表分成若干个ziplist减少空间同事提升性能
4.集合类型
ht或者INTset
数量少于指定value的整数 时采用intset,不满足自动切换为ht,并且不会变回去,
intset有序,可以二分查找但是插入删除性能差(动内存)
5.有序集合
skiplist或者ziplist
如果使用skiplist :散列表元素值->分数 跳表分数->元素值,按照redisobject类型存储
使用zip:元素1的值,元素1的分数,元素2的值…