Redis系列(5)—— 排序与订阅
Redis 提供了五种数据结构(String、Hash、List、Set、Sorted-Set),还有一些不是数据结构的命令。
例如一些有用的命令:info,select,flushdb,expire,ttl, presist,multi,exec,discard,watch,keys
本文介绍一些其他的重要的命令。
过期时间 (expire)
Redis提供了你一个key 的存活期限,你可以给一个绝对时间(自1970年1月1日到现在的秒),或者一个相对时间,即从现在开始的秒数。
这是基于key的命令,其value是什么都无所谓。
过期函数请见米扑博客:php-redis 各种函数中文手册
expire pages:about 30 // 30秒后过期(删除)
expireat pages:about 1256933600 // 在时间戳1256933600时过期(删除)
第一个命令会在30秒后删除key
第二个做同样的是在2012年11月31号的12点
这使Redis变成一个理想的缓冲引擎,可以通过ttl
命令查看一个key 存活了多久,
你也可以通过 presist 来删除一个key的过期时间:
ttl pages:about // 结果 25
presist pages:about // 结构 1256933600
最后,这有一个特殊的命令,setex
让你设置指定的string,他是一个原子命令:
setex pages:about 30 '<h1>about us</h1>....'
setex 格式:SETEX key seconds value 时间复杂度为 O(1)
原子性完成两个操作,一是设置该Key的值为指定字符串,同时设置该Key在Redis服务器中的存活时间(秒数)。
setex 命令主要应用于Redis被当做Cache服务器使用时。
更多请见米扑博客:Redis实例(2)—— string
发布和订阅
Redis的list有blpop
和brpop
命令。
他们返回删除的第一个元素并且返回,这可以很有用的用到一个简单的队列里。
基于这些,Redis很好的提供发布信息和订阅频道的功能。
你可以打开一个新的redis-cli串口试试。
在第一个窗口订阅频道:
subscribe warnings
回应小心。现在你在另一个窗口,发布一个消息:
publish warnings "hello yanggang"
这时切换回到第一个窗口,你会接收到消息"hello yanggang"
发布订阅示例:
1) 订阅端
homer@ubuntu:/opt/redis-2.8.7$ /opt/redis-2.8.7/src/redis-cli
127.0.0.1:6379> subscribe warnings
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "warnings"
3) (integer) 1
1) "message"
2) "warnings"
3) "hello yanggang" # 接收第一条
1) "message"
2) "warnings"
3) "hello https://blog.mimvp.com" # 接收第二条
2)发布端
homer@ubuntu:~$ redis-cli
127.0.0.1:6379> publish warnings "hello yanggang" # 发布第一条
(integer) 1
127.0.0.1:6379> publish warnings "hello https://blog.mimvp.com" # 发布第二条
(integer) 1
你可以订阅多个频道(subscribe channel1 channel2 …)订阅频道的模式(psubscribe warnings:*) 用unsubscribe
和 punsubscribe
命令停止监听。
Python 发布订阅实现:
#!/usr/bin/env python # -*- coding: utf-8 -*- # https://blog.mimvp.com import time import redis import threading class Listener(threading.Thread): def __init__(self, r, channels): threading.Thread.__init__(self) self.redis = r self.pubsub = self.redis.pubsub() # 发布订阅对象 self.pubsub.subscribe(channels) # 订阅 def work(self, item): print item['channel'], ":", item['data'] def run(self): for item in self.pubsub.listen(): print item if item['data'] == "KILL": print self, "unsubscribed and finished" self.pubsub.unsubscribe() # 取消订阅 break else: self.work(item) time.sleep(3) # 暂停1秒 if __name__ == "__main__": r = redis.Redis() client = Listener(r, ['test', 'test2']) # 仅订阅 'test', 'test2', 'fail' 将被过滤掉 client.start() r.publish('test', 'this will reach the listener') r.publish('test2', 'this will work') r.publish('fail', 'this will not') # 被过滤掉了 r.publish('test', 'KILL')
运行结果:
{'pattern': None, 'type': 'subscribe', 'channel': 'test', 'data': 1L}
test : 1
{'pattern': None, 'type': 'subscribe', 'channel': 'test2', 'data': 2L}
test2 : 2
{'pattern': None, 'type': 'message', 'channel': 'test', 'data': 'this will reach the listener'}
test : this will reach the listener
{'pattern': None, 'type': 'message', 'channel': 'test2', 'data': 'this will work'}
test2 : this will work
{'pattern': None, 'type': 'message', 'channel': 'test', 'data': 'KILL'}
<Listener(Thread-1, started 140189318100736)> unsubscribed and finished
最后,注意publish
命令返回的值:1 就是监听客户端的数量。
监控和慢记录
monitor
命令让你了解Redis运行状况,可以很好的调试了解你的应用程序与Redis的联系。
在其中一个redis-cli的窗口中(如果你还在subscribed,你可以用unsubscribe命令取消,或者关闭重新开一个)敲入monitor
命令。
在另一个redis-cli的窗体,执行一个命令,你可以看到这些信息。
在生产环境上用还是要注意吧,因为 monitor 是一个开发和测试工具。
配合这monitor,Redis还有一个slowlog
慢查询是一伟大的分析工具。
slowlog命令会log出消耗超过指定毫秒(单位ms)的命令,你能配置Redis log出所有的命令:
config set slowlog-log-slower-than 0
下一步,用一些命令,最后你能得到所有的log。
获得最近的logs,是通过如下命令:
slowlog get
slowlog get 10
你也可以获得数量通过输入slowlog len
从每个你输入的命令你能看到4个参数:
- 一个自增的id
- 一个命令产生的时间戳
- 命令消耗多少时间(ms)
- 命令本身和参数
slowlog在内存中维护,所以在生产环境中要慎重。
排序
Redis最重要的命令之一就是排序。他让你在 list,set,sorted set 中排序。
在最简单的形式:
rpush users:leto:guesses 5 9 10 2 4 10 19 2
sort users:leto:guesses
上面返回的是从低到高的排序后结果。
sadd friends:ghanima leto paul chani jessica alia duncan
sort friends:ghanima limit 0 3 desc alpha
在上面的命令展示出我们应该如何分页排序好的记录(通过limit),怎么获得倒序(通过desc),通过字典排序规则代替数字规则(通过 alpha)。
排序的真正强大之处应该是根据引用的object排序。
之前我们展示了lists,sets,sorted sets经常引用其他Redis的object。
sort
命令很有用,通过一些值排序。
举个例子,我们有一个bug追踪器,能让用户看到问题,我们可能会用set去跟踪:
sadd watch:leto 12339 1282 338 9338
这可能会根据id排序会更好(默认就是这么做的),但是我们也想根据严重等级排序。
为了这么做我们会告诉Redis排序的参数。首先我们增加一些对结构有意义的数据:
set severity:12339 3
set severity:1382 2
set severity:338 5
set severity:9338 4
通过严重等级排序bugs:
sort watch:leto by severity:* desc
Redis会替换*为我们传的参数,这会创建实际的key对应的value,然后排序。
虽然你可以在Redis中有很多的kyes,我想上面的例子你可能会有凌乱。
幸好排序也同样适合在hashes的字段上。替换最高级的keys你可以用hashes:
hset bug:12339 severity 3
hset bug:12339 priority 1
hset bug:12339 details ”{id: 12339, ....}”
hset bug:1382 severity 2
hset bug:1382 priority 2
hset bug:1382 details ”{id: 1382, ....}”
hset bug:338 severity 5
hset bug:338 priority 3
hset bug:338 details ”{id: 338, ....}”
hset bug:9338 severity 4
hset bug:9338 priority 2
hset bug:9338 details ”{id: 9338, ....}”
不仅整齐了,我们还能通过severity或者priority排序,同时我们还可以通过排序获得:
sort watch:leto by bug:*->priority get bug:*->details
同样的结果。Redis认出->序列,然后查找出hash里的指定字段。
我们同时也加了get参数,定义了子查询来获得bug的详细信息。
在大set里,排序会变得很慢。好消息是排过序的输出可以存储:
sort watch:leto by bug:*->priority get bug:*->details store watch_by_priority:leto
存储一个排序后的结果,做一个漂亮的连招。
小结
在这章我们关注非数据结构命令,这些命令因情况而定,
不一定每个应用都会用到 expiration,publication/subscription或者排序。
但是在这都有了解,我们在这只用了其中一些命令,
文档上会有全部的命令:http://redis.io/commands
参考推荐:
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2021-01-21 11:55:50
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!