Redis学习笔记---进阶篇

Redis学习笔记—进阶篇

一、事务

1.MULTI命令

Redis中的事务(transaction)是一组命令的集合。一个事务中的命令要么都执行,要么都不执行。Redis通过MULTI开启事务,之后的命令将被存储在等待执行的事务队列中,使用EXEC命令将等待执行的事务队列中的所有命令按照发送顺序依次执行。EXEC命令的返回值就是这些命令的返回值组成的列表。返回值顺序和命令的顺序相同。

127.0.0.1:6379> multi
OK

127.0.0.1:6379> sadd "user:1:following" 2
QUEUED
127.0.0.1:6379> sadd "user:2:followers" 1
QUEUED

127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1

2.错误处理

a. 语法错误。指命令不存在或者命令参数的个数不对。只要有一个命令有语法错误,执行EXEC命令之后Redis就会直接返回错误,连语法正确的命令也不会执行。

127.0.0.1:6379> multi
OK

127.0.0.1:6379> set key value
QUEUED
127.0.0.1:6379> set key
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> errorcommand key
(error) ERR unknown command `errorcommand`, with args beginning with: `key`,

127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

b. 运行错误。如果事务里的一条命令出现了运行错误,事务里其他的命令依然会继续执行。

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> get key
"3"

Redis的事务没有关系数据库事务提供的回滚(rollback)功能。

3.WATCH命令

watch命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不执行。监控一直持续到EXEC命令。

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"

执行EXEC命令后会取消对所有键的监控,如果不想执行事务中的命令也可以使用UNWATCH命令来取消监控。

二、过期时间

1.EXPIRE命令

使用expire命令设置一个键的过期时间,到时间后Redis会自动删除它。

EXPIRE命令的使用方法为 EXPIRE key seconds,其中seconds参数表示为键的过期时间,单位为秒。

EXPIRE命令返回1表示设置成功,返回0则表示键不存在或设置失败

TTL命令可以查看一个键还有多少时间会被删除。当键不存在时TTL命令返回-2没有为键设置过期时间返回为 -1.

127.0.0.1:6379> set  username jenkin
OK
127.0.0.1:6379> expire username 60
(integer) 1

127.0.0.1:6379> ttl username
(integer) 44

127.0.0.1:6379> del username
(integer) 1

127.0.0.1:6379> expire username 60
(integer) 0

127.0.0.1:6379> ttl username
(integer) -2

127.0.0.1:6379> set username jenkin
OK

127.0.0.1:6379> ttl username
(integer) -1

PERSIST命令可以取消键的过期时间(即将键恢复成永久的)。如果过期时间被成功清除,则返回1,否则返回0.

127.0.0.1:6379> set foo bar
OK

127.0.0.1:6379> expire foo 44
(integer) 1

127.0.0.1:6379> persist foo
(integer) 1

127.0.0.1:6379> ttl foo
(integer) -1

使用setgetset命令为键赋值也会同时清除键的过期时间。

EXPIRE命令的seconds参数必须是整数,最小单位是1秒。

PEXPIRE命令可以设置更精确的过期时间,最小单位是1毫秒,可以使用PTTL命令以毫秒为单位返回键的剩余时间。

2.缓存

通过修改配置文件/usr/local/etc/redis.conf(mac系统,通过homebrew安装的Redis)的maxmemory参数,限制Redis最大可用内存大小(单位是字节),当超出这个限制时Redis会根据maxmemory-policy参数指定的策略来删除不需要的键直到Redis占用的内存小于指定内存。默认的策略是noeviction

maxmemory-policy支持的规则:

volatile-lru:使用LRU算法删除一个键(只对设置了过期时间的键)

allkeys-lru:使用LRU算法删除一个键

volatile-random:随机删除一个键(只对设置了过期时间)

allkeys-random:随机删除一个键

volatile-ttl:删除过期时间最近的一个键

noeviction:不删除键,只返回错误

三、排序

1.有序集合的集合操作

有序集合的操作是将运算结果存入新的键中,以便后续处理。比如zinterstorezunionstore等操作。如果需要直接获取运算结果,可以使用multi、zinterstore、zrange、del和exec等命令自己实现。

127.0.0.1:6379> sadd num1 1 2 3
(integer) 3
127.0.0.1:6379> sadd num2 2 3 4
(integer) 3

127.0.0.1:6379> multi
OK
127.0.0.1:6379> zinterstore d 2 num1 num2
QUEUED
127.0.0.1:6379> zrange d 0 -1
QUEUED

127.0.0.1:6379> exec
1) (integer) 2
2) 1) "2"
   2) "3"

2.SORT命令

sort命令可以对列表类型、集合类型和有序集合类型键进行排序。

127.0.0.1:6379> lpush score 45 89 76 65 91
(integer) 5
127.0.0.1:6379> lrange score 0 -1
1) "91"
2) "65"
3) "76"
4) "89"
5) "45"

127.0.0.1:6379> sort score
1) "45"
2) "65"
3) "76"
4) "89"
5) "91"

在对有序集合类型排序时会忽略元素的分数,只针对元素自身的值进行排序。

127.0.0.1:6379> zadd myzset 50 2 40 3 20 1 60 5
(integer) 4
127.0.0.1:6379> sort myzset
1) "1"
2) "2"
3) "3"
4) "5"

除了可以对数字排列外,还可以通过ALPHA参数实现按照字典顺序排列非数字元素。

sort默认是按从小到大的顺序排列,通过DESC参数可以实现将元素按照从大到小的顺序排列。LIMIT参数返回指定范围的结果。

127.0.0.1:6379> lpush letter a d c G B e F
(integer) 7

127.0.0.1:6379> sort letter
(error) ERR One or more scores can't be converted into double

127.0.0.1:6379> sort letter alpha
1) "B"
2) "F"
3) "G"
4) "a"
5) "c"
6) "d"
7) "e"

127.0.0.1:6379> sort letter alpha desc
1) "e"
2) "d"
3) "c"
4) "a"
5) "G"
6) "F"
7) "B"

127.0.0.1:6379> sort letter alpha desc limit 2 4
1) "c"
2) "a"
3) "G"
4) "F"

3.BY参数

语法为 BY 参考键,参考键可以是字符串类型键或者是散列类型键的某个字段(表示为键名->字段名)

如果提供了BY参数,sort命令将不再依据元素自身的值进行排序,而是对每个元素使用元素的值替换参考键中的第一个“*”并获取其值,然后依据该值对元素排序。

127.0.0.1:6379> lpush l 2 1 3
(integer) 3
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
OK

127.0.0.1:6379> sort l by itemscore:*
1) "3"
2) "1"
3) "2"
127.0.0.1:6379> sort l by itemscore:* desc
1) "2"
2) "1"
3) "3"

当参考键名不包含“*”时(即常量键名,与元素值无关),sort命令将不会执行排序操作。

如果几个元素的参考键值相同,则sort命令会再比较元素本身的值来决定元素的顺序。

当某个元素的参考键不存在时,会默认参考键值的值为 0.

4.GET参数

get参数不影响排序,他的作用是使sort命令的返回结果不再是元素自身的值,而是GET参数中指定的键值。get参数也支持字符串类型和散列类型的键,并使用“*****”作为占位符。有N个get参数,每个元素返回的结果就有N行。

127.0.0.1:6379> sort tag:ruby:posts by post:*->time desc get post:*->title get post:*->time get #
1) "Windows 8 app designs"
2) "1345667878"
3) "12"
4) "Uses for cURL"
5) "1345667877"
6) "12"
7) "The nature of ruby"
8) "1345667876"
9) "6"

get # 会返回元素本身的值

5.STORE参数

默认下SORT会直接返回排序结果,如果希望保存排序结果,可以使用STORE参数。保存后的键的类型为列表类型,如果键已经存在则会覆盖它。加上store参数后sort命令返回的是结果的个数。

127.0.0.1:6379> sort tag:ruby:posts by post:*->time desc get post:*->title get post:*->time get # store sort.result
(integer) 9

127.0.0.1:6379> lrange sort.list 0 -1
1) "Windows 8 app designs"
2) "1345667878"
3) "12"
4) "Uses for cURL"
5) "1345667877"
6) "12"
7) "The nature of ruby"
8) "1345667876"
9) "6"

STORE参数常用来结合EXPIRE命令缓存排序结果。

6.性能优化

SORT命令的时间复杂度O(n+mlog(m)),其中n表示要排序的列表中的元素个数,m表示要返回的元素个数。

使用SORT命令时需注意几点:

①尽可能减少待排序键中元素的数量(使N尽可能小)。

②使用LIMIT参数只获取需要的数据(使M尽可能小)。

③如果要排序的数据数量较大,尽可能使用STORE参数将结果缓存。

四、消息通知

1.任务队列

使用任务队列的好处:

​ ①松耦合:生产者和消费者无需知道彼此的实现细节,只需要约定好任务的描述格式。

​ ②易于扩展:消费者可以有多个,而且可以分布在不同服务器中,也能降低单台服务器的负载。

2.使用Redis实现任务队列

通过使用LPUSHRPOP命令就可实现队列的概念。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一个边让消费者不断地使用RPOP命令从改建中取出任务即可。

BRPOP命令与RPOP命令相似,区别在于当列表中没有元素时BRPOP命令会一直阻塞住连接,直到有新的元素加入。

BRPOP命令接收两个参数:第一个是键名,第二个是超时时间,单位是秒,当超过此时间仍然没有获得新元素的话就会返回nil。超时时间为”0“,表示不限制等待时间,即如果没有新元素加入列表就会永远阻塞下去。

3.队列优先级

BRPOP命令可以同时接收多个键,意义是同时检测多个键,如果所有键都没有元素则阻塞,如果其中有一个键有元素则会从该键中弹出元素。

如果多个建都有元素则按照从左到右的顺序取第一个键中的一个元素。

4."发布/订阅"模式

发布/订阅“模式中包含两种角色,分别是发布者订阅者。订阅者可以订阅一个或若干个频道(channel),而发布者可以向指定的频道发送消息,所有订阅此频道的订阅者都会收到此消息。

  1. 发布者发布消息的命令是PUBLISH,用法是 PUBLISH channel message。发出去的消息不会被持久化,也就是说当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的就收不到了。

  2. 订阅频道的命令是SUBSCRIBE,可以同时订阅多个频道,用法是 SUBSCRIBE channel [channel...]。

  3. UNSUBSCRIBE命令可以取消订阅指定的频道,如果不指定频道则会取消订阅所有频道。

5.按照规则订阅

使用PSUBSCRIBE命令可以订阅指定的规则。

PUNSUBSCRIBE命令可以退订指定的规则,如果没有参数则会退订所有规则。

使用PUNSUBSCRIBE命令只能退订通过PSUBSCRIBE命令订阅的规则,不会影响直接通过SUBSCRIBE命令订阅的频道。UNSUBSCRIBE命令也不会影响通过PSUBSCRIBE命令订阅的规则。

五、管道

不管是客户端向Redis发送命令还是Redis向客户端返回命令的执行结果,都需要经过网络传输,这两个部分的总耗时称为往返时延

Redis的底层通信协议对管道(pipelining)提供了支持。通过管道可以一次性发送多条命令并在执行完后一次性将结果返回,当一组命令中每条命令都不依赖于之前命令的执行结果时就可以将这组命令一起通过管道发出。管道通过减少客户端与Redis的通信次数来实现降低往返时延累计值的目的。

六、节省空间

1.精简键名和键值

2.内部编码优化


个人博客:https://jenkinwang.github.io/

参考书籍:《Redis入门指南(第二版)》李子骅 编著

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容