Redis 提供了五种数据结构(String、Hash、List、Set、Sorted-Set),还有一些不是数据结构的命令。

例如一些有用的命令:info,select,flushdb,multi,exec,discard,watch,kyes

本文介绍一些其他的重要的命令。

 

 

过期时间 (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 存活了多久,你也可以删除一个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有blpopbrpop命令。他们返回删除的第一个元素并且返回,这可以很有用的用到一个简单的队列里。

基于这些,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,Redis有一个slowlog这是一伟大的分析工具。

他会log出消耗超过指定毫秒的命令,你能配置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

 

 

参考推荐

Redis实例(2)—— string

Redis系列(4)—— 高级功能

PHP-redis 中文文档

php-redis 各种函数中文手册