一. 安装配置
Redis是key-value型数据库,支持多种value类型(string、lists、sets、hash等),提供多种语言的API。
sudo apt-get install redis-server #这里我们服务器端和客户端都在本地机器上
服务器端安装完后,/etc/redis/redis.conf即为相应的配置文件,其中默认设置了host=‘127.0.0.1’, port=6379,创建0号至15号共16个数据库供用户使用(数据库的数量也可修改 - databases选项),后台进程是默认打开的(daemonize yes设置)
sudo pip install redis #安装redis客户端
sudo apt-get install python-redis #也可以安装redis客户端
二. 使用
2.1 一般方法
import redis
r = redis.StrictRedis(host='', port=, db=0) #也可以使用redis.Redis(),Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py,部分API使用方法与redis-cli命令行操作不同
r.set('foo', 'bar') #存储{key:value} -> {'foo':'bar'}
r.get('foo') #获取key对应的value
r.keys() #查看所有的keys,因此redis实例的用法类似于python的字典
r.delete('foo') #删除foo这一项
r.flushdb() #清空数据库
2.2 连接池connection pool
在后台,redis是通过连接池来管理对于Redis服务端的连接的。默认的话,每创建一个redis实例都会去创建一个连接池。用户可以重用已有的连接池来创建新的实例,这样的话同一个连接池的实例可以实现共享及对连接的细粒度控制。
pool = redis.ConnectionPool(host='', port=, db=)
r = redis.Redis(connection_pool=pool)
2.3 hash类型
当要存储的一个键值key:item,其中item本身也包含field-value这种对应信息时,当用户只想获得item中某个属性的值时,一般方法会将整个item取出来,这是非常浪费IO的。
redis提供的散列类型HASH可以解决这个问题,即将上述key作为一个hash类型中的key,然后item中的field-value也可以当作一般方法中的key和value保存下来。因此hash类型相关操作,仅比一般方法多了一个hash key的指定和映射(类似二维数组的概念,一般方法是一维数组)。
r.hset(key, field, value) #将哈希表key中的字段field的值设为value
r.hget(key, field) #获取存储在哈希表key中指定字段field的值
r.hmset(key, field_value) #批量添加属性,field_value是一个字典(若属性没有则创建)
r.hmget(key, fields, *args) #批量读取属性的值
r.hgetall(key) #获取存储在哈希表key中的所有field对应的值,返回字典类型
r.hkeys(key) #获取所有属性field名,返回列表类型
r.hdel(key, field) #删除指定属性field一项
2.4 sets类型
上面说过redis能支持多种数据类型,除了string、hash,还有一种主要的类型是集合sets,和数学上集合的概念一样,即不能有重复元素。存储sets类型数据时,需要提供一个key,可以理解为集合变量的名称,存储的值即为value。
r.sadd(key, val) #往key集合添加单个成员val,若val在key中存在则不添加
r.sadd(key, val1, val2,...) #往集合中添加多个成员(以,分隔),已经存在于集合的会被忽略。
r.srem(key, val1, val2,...) #从集合中移除成员,会忽略集合中不存在的元素
r.smembers(key) #返回集合中所有成员
r.sismember(key, val) #判断val元素是否在集合key中
r.scard(key) #返回集合key中元素的个数
2.5 其他用法
pub/sub是目前广泛使用的通信模型,采用事件作为基本的通信机制,提供大规模系统所要求的松散耦合的交互模式。
该模型有3种非耦合特性:
- 时间非耦合:双方不必同时在线,同时参与交互
- 空间非耦合:双方通过事件服务相关交互,不需知道对方的位置
- 同步非耦合:双方是异步模式,发布者可不断生产事件,而订阅者可异步地得到产生事件的通知
r.publish(channel, data) #发布功能(发布者指的是服务器) 通过channel发布data信息
r.subscribe(channel) #订阅功能(订阅者指的是客户端) 通过channel订阅信息
r.listen() #接收订阅到的信息,即返回data相关信息
订阅的API也可以如下:
p = r.pubsub()
p.subscribe(channel)
p.listen()
三. 扩展
3.1 redis和celery配合使用
celery是基于python开发的分布式任务队列,它的架构由三部分组成:
- 消息中间件:celery本身不提供消息服务,但可以与第三方消息中间件(message broker)集成,包括RabbitMQ, Redis等
- 任务执行单元:Worker是celery提供的执行任务的单元
- 任务结果存储:celery支持不同方式存储任务的结果,包括AMQP,Redis,memcached等
一般流程:
python文件中定义celery任务,其中需要先定义一个Celery实例,然后定义任务需要执行的函数
命令行开启celery worker server,从此该服务器就会等待用户执行任务的请求从而去执行第一步定义的任务
在python文件中调用该任务
from tasks import add add.delay(4,4)
注意点:
a) 命令行开启celery worker server时,可以添加选项
如:celery -A tasks worker -l info -n worker.%h -Q for_task_A
-n参数表示这个worker的name, -Q参数指定了这个worker只执行for_task_A队列中的消息
因此定义任务时需要添加路由信息,表明哪个任务task会发送到哪个消息队列queue中:
app.conf.task_routes = {'taskA': {**'queue'**: 'queueA'}
'taskB': {**'queue'**: 'queueB'} } 其中加粗的**'queue'**是关键字
b) 在调用任务时,如taskA.delay(arg),其中参数arg如果是str类型的,则传输到定义的函数体内会变成unicode类型;如果是int类型,传输进去还是int类型