Django笔记:Redis键值对数据库
Redis是一种nosql数据库(非关系型数据库),它的数据是以键值对的形式保存在内存中的,同时也可以定时将数据同步到磁盘文件中,即实现数据的持久化,相比于Memcached缓存系统,它支持更多的数据结构,如string、list(队列和栈)、set(集合)、sorted set(有序集合)、hash(hash表)等。本文只是简单整理了下学习笔记,感兴趣的话可以查看中文官方文档。
一、使用场景和特点
1. 常用的使用场景
- 登录会话存储:存储在Redis中,与Memcached相比,数据不会丢失。
- 排行榜或计数器:一些实时的排行或计数都可以采用Redis来实现。
- 消息队列:如celery就是使用Redis作为中间人。
- 当前在线人数:实时的数据,但是又不需要存储到数据库中,可以采用Redis来实现。
- 常用的数据缓存:如论坛的首页等不会经常变化的数据存储到Redis中。
- 前100文章或评论进行缓存:一般情况下,用户浏览数据只会浏览前面的部分,可以把这些经常访问的数据缓存到Redis数据库中。
- 好友关系:微博的好友关系就是使用Redis实现的。
- 发布和订阅功能:可以用来做聊天软件。
2. 和Memcached的比较
| 比较项 | Memcached | Redis |
|---|---|---|
| 类型 | 纯内存缓存系统 | 内存到磁盘同步数据库 |
| 数据类型 | 在定义value时就需要指定数据类型 | 不需要 |
| 虚拟内存 | 不支持 | 支持 |
| 过期策略 | 支持 | 支持 |
| 存储数据安全 | 不支持 | 可以将数据同步到磁盘文件中 |
| 灾难恢复 | 不支持 | 可以将磁盘中的数据恢复到内存中 |
| 分布式 | 支持 | 支持,主从同步方式 |
| 订阅与发布 | 不支持 | 支持 |
二、安装和使用
1. 安装与连接
Redis是不支持Windows系统的,只能在Linux上进行操作。以下示例的命令以ubuntu系统为例。
安装:sudo apt-get install redis-server。
卸载:sudo apt-get purge --auto-remove redis-server。
启动:安装后默认自动启动,可以通过命令查看进程信息ps aux|grep redis。也可以通过命令手动启动sudo service redis-server start(重启就是restart)。
停止:sudo service redis-server stop。
连接redis-server:可以使用命令redis-cli进行连接,相当于Redis的客户端,命令格式为redis-cli -h [ip] -p [port],如redis-cli -h 127.0.0.1 -p 6379,Redis默认的启动端口为6379。
设置密码:在配置文件/etc/redis/redis.conf中放开requirepass password项,并将password替换为对应的密码即可。设置密码后还是可以正常连接,但是连接之后需要先执行auth [password]后才能进行正常的数据更新等操作,不然无法进行正常的操作。当然也可以在连接时是用-a参数指定密码,如redis-cli -h 127.0.0.1 -p 6379 -a 123456。
其他机器连接本机Redis:默认只能本机连接,如果想要其他机器也能连接到本机的Redis,则需要在配置文件/etc/redis/redis.conf中给bind 127.0.0.1之后添加具体的本机ip,如bind 127.0.0.1 xxx.xxx.xxx.xxx,其他机器就能通过后面这个ip来进行连接了。
2. 常用基础操作
添加:使用set和get命令进行数据的添加和获取,添加数据时默认为字符串类型,如果设置的值中含有空格则需要使用双引号包裹起来。
127.0.0.1:6379> set username zhangsan
OK
127.0.0.1:6379> get username
"zhangsan"
127.0.0.1:6379> set username "zhang san"
OK
127.0.0.1:6379> get username
"zhang san"
删除:使用del命令进行删除。
127.0.0.1:6379> del username
(nil)
设置过期时间:添加数据时如果没有设置过期时间,则默认为永久不过期。可以采用两种方式设置过期时间,一种是在添加值时进行设置:set key value EX timeout或setex key timeout value,另一种是对已经存在的值进行设置:expire key timeout。timeout单位为秒。
查看过期时间:通过命令ttl key进行查看。
查看所有的key:通过命令keys *进行查看。
删除全部数据:flushall删除全部键值对,实际工作中慎用。
3. 常用列表操作
Redis中列表操作是有专门的命令来执行的,而不是先创建一个列表,再对列表进行操作。
在列表头/尾添加数据:lpush/rpush key value。将value插入到key对应的列表的表头/尾,如果key不存在,则创建一个空列表并执行lpush/rpush操作,如果key对应的值不是列表,则会返回一个错误。
查看列表元素:lrange key start stop。返回列表内指定区间的元素,如果要查看全部元素,则可以使用命令lrange key 0 -1。
移除列表头/尾元素:lpop/rpop key。移除(弹出)列表头/尾的一个元素并返回。
移除列表多个元素:lrem key count value。删除列表中指定count个数的value元素。count大于0时,表示从表头开始搜索并删除指定个数值为value的元素;count小于0时,表示从表尾开始搜索并删除指定个数(绝对值)值为value的元素;count等于0时,表示删除全部值为value的元素。
根据索引查看列表元素:lindex key index。查看指定索引的元素。
查看列表元素个数:llen key。查看列表中的元素个数。
4. 常用集合操作
同列表一样,不需要先创建集合,再进行集合操作,在往key中添加集合数据时,如果没有则会自动创建该集合。
添加集合元素:sadd key value1 value2 ...。往集合中添加数据,可以一次添加多个值。
查看集合元素:smembers key。查看集合中的元素。
移除集合元素:srem key value1 value2。移除集合中的元素,可以一次移除多个元素。
查看集合中的元素个数:scard key。查看集合中的元素个数。
查看多个集合的交集:sinter key1 key2。查看多个集合的交集。
查看多个集合的并集:sunion key1 key2。查看多个集合的并集。
查看多个集合的差集:sdiff key1 key2。查看多个集合的差集。
5. 常用hash操作
哈希操作指的是value的数据类型为字典,同样的,不需要先创建hash表(字典)再进行操作,在添加数据时,如果hash表不存在则会自动创建。
添加数据:hset key field value。在key对应的hash表(字典)中添加一个新的键值对field/value。hmset key field1 value1 field2 value2 ...:一次添加多个键值对。
查看数据:hget key field。查看key对应的hash表(字典)中field对应的值。
删除数据:hdel key field。删除key对应的hash表(字典)中field对应的值。
查看所有的子键值对:hgetall key。查看key对应的hash表(字典)中所有的field/value。
查看所有的key:hkeys/hvals key。查看key对应的hash表(字典)中所有的field或value。
查看是否存在某个key:hexists key field。查看key对应的hash表(字典)中是否存在指定的field。
查看子键值对个数:hlen key。查看查看key对应的hash表(字典)中的键值对个数。
6. 常用事务操作
Redis事务可以一次执行多个命令,具有以下两个基本特征:
- 隔离操作:事务中的所有命令都会序列化、按顺序执行,不会被打断。
- 原子操作:事务中的命令要么全部执行,要么全部不执行。
开启一个事务:multi。执行这个命令后就开启了一个事务,之后的所有命令都不会被真正的执行,而是在执行该事务的时候一起执行事务中的所有命令。
执行事务:exec。执行事务中的所有命令,如果事务中的命令有报错,则该事务也会执行失败。
取消事务:discard。在使用multi命令后,执行exec命令之前,可以使用discard命令取消并退出事务。
监视:watch key1 key2 ..。监视一个或多个key,在指定监视后,在定义事务过程中,如果该key的值发生了变化,那么执行事务时,对该key的值的修改将不会生效。
取消监视:unwatch。取消监视所有的key。
7. 发布订阅操作
给某个频道发布消息:publish channel message。channel名称和message内容都可以自定义。
订阅某个频道的消息:subscribe channel1 channel2 ...。执行这个命令后,程序相当于进入了一个死循环,会一直等待发布者发布消息,一旦发布者发布了消息,那么此订阅程序就能马上收到消息。
三、持久化机制
Redis提供了两种持久化机制或者说备份方式,即RDB和AOF,它们的存储方式都是存储在磁盘的特定文件中,这两种方式的配置信息都在配置文件/etc/redis/redis.conf中,它们各自的特点可以参考如下表格。
| 比较项 | RDB | AOF |
|---|---|---|
| 开启和关闭 | 默认开启。如果想要关闭,则注释掉配置文件中SNAPSHOTTING下相关save即可,如save 900 1表示如果900秒内发生了一次数据更新操作则进行一次同步,其他save也是同理,相当于每隔一定时间会检查一次,如果数据更新次数达到配置的要求则会进行同步,这也是RDB默认的同步机制。 |
默认关闭。如果想要开启,修改配置文件中appendonly no为appendonly yes即可。 |
| 同步机制 | 根据配置文件中save项配置值,每隔一定时间会检查一次,如果数据更新次数达到配置的要求则会进行同步。 |
配置文件中提供了三种同步方式,可以根据需要打开对应的同步方式即可:appendfsync always(每发生一次更新操作则同步一次),appendfsync everysec(默认,每秒同步一次),appendfsync no(采用操作系统的更新方式,每30秒同步一次)。 |
| 存储内容 | 存储的是具体的键值对,如username: zhangsan,并且数据是经过压缩的。 |
存储的是对应的操作命令,如set username zhangsan,且数据没有经过压缩。 |
| 存储文件的路径 | 根据配置文件中dir(默认/var/lib/redis)和dbfilename(默认dump.rdb)两个参数来指定。 |
根据配置文件中dir(默认/var/lib/redis)和appendfilename(默认appendonly.aof)两个参数来指定。 |
| 优点 | 1)因为存储的数据经过压缩,所以文件体积比AOF小。2)因为存储的是具体的键值对,所以恢复速度比AOF块。3)适用于备份操作。 | 1)因为默认是每秒同步一次,所以即使发生了故障,丢失的数据也不会太多。2)因为存储的时候是在文件末尾追加命令,所以备份速度会比较快。3)如果文件过大时,AOF会对文件中的命令进行重写,只保留最小的命令集。 |
| 缺点 | 1)因为每次同步都会将整个文件重新压缩一次,所以一般会将同步的时间间隔设置的较长,而在这个时间内如果发生故障,则会丢失对应的数据。2)每次同步Redis都会fork出一个子进程来进同步操作,当数据量比较大的时候可能会非常耗时。 | 1)因为文件没有经过压缩,所以文件体积会比RDB大。2)因为每秒就会进行一次同步,所以并发量较大时,效率可能会较低。3)因为存储的是命令,所以在灾难恢复的时候会比RDB慢。 |
四、Python操作Redis
安装:pip install redis。
Python中对应操作的方法名大多和客户端操作时的命令是一致的,可以参考命令来使用,下面只展示部分的操作方法,更多方法可以查看源码。
from redis import Redis
# 连接Redis
cache = Redis(host='192.168.1.17', port=6379, password='123456')
# 1. 普通键值对,即value为字符串类型
# 添加数据,可以使用ex参数指定过期时间
cache.set('username', 'zhangsan')
# 获取数据
print(cache.get('username'))
# 删除数据
cache.delete('username')
# 2. 列表操作
# 添加数据
cache.lpush('languages', 'python')
cache.lpush('languages', 'java')
# 获取数据
print(cache.lrange('languages', 0, -1))
# 3. 集合操作
# 添加数据
cache.sadd('person', 'zhangsan')
cache.sadd('person', 'lisi')
# 获取数据
print(cache.smembers('person'))
# 4. hash操作
# 添加数据
cache.hset('person', 'name', 'zhangsan')
cache.hset('person', 'age', '18')
# 获取数据
print(cache.hgetall('person'))
# 5. 事务操作
# 创建管道(事务)
pl = cache.pipeline()
# 添加命令
pl.set('username', 'lisi')
pl.set('age', '20')
# 执行事务
pl.execute()
# 6. 发布与订阅操作
# 监听操作
ps = cache.pubsub()
# 订阅频道
ps.subscribe('mychannel')
while True:
# 监听消息
for message in ps.listen():
print(message)
'''
# 发布消息(在另一个程序中运行)
from redis import Redis
# 连接Redis
cache = Redis(host='192.168.1.17', port=6379, password='123456')
# 发布消息
for i in range(5):
cache.publish('mychannel', 'xxxxx@qq.com')
'''
注:本文为学习笔记,发现错误欢迎指出。

浙公网安备 33010602011771号