Redis与python
一、Redis介绍
Redis是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库(非关系型数据库)。
本质:将数据保存在内存中。
用途:缓存、消息队列。
1、Redis的特点
Redis支持五种数据类型:字符串、列表、哈希散列表、集合、有序集合。和Memcached类似,但它支持存储的values类型相对更多。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启时可以再次加载进行使用。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis支持数据库备份。
2、Redis优势
Redis性能极高,读的速度是110000次/s,写的速度是8100次/s。
Redis丰富的数据类型(String、Lists、Hashes、Sets、Ordered Sets)。
Redis的所有操作都是原子性的,要么成功执行、要么完全失败不执行,多个操作支持事务,即MULTI和EXEC指令包起来。
Redis有丰富的特性,支持publish/subscribe(发布/订阅者模式),通知,key过期等特性。
3、memcached & redis异同
相同点:都是NoSQl数据库,数据存到内存,读取速度快 好处如下: 1.减少数据库压力,提升访问速度 2.在数据挂掉的情况下,仍能保证业务正常运行一段时间,提升安全性 不同点: (1)类型 memcached:类型单一,只能存字符串"key为字符串"="value也为字符串" redis:支持五大类型:string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)、hash(哈希类型) (2)持久化 memcached:断电数据丢失 redis:支持持久化,单独开一个进程完成持久化,要保持性能就需要关闭持久化,很多公司并不使用持久化功能
4、Redis数据类型
String字符串:可以包含任何数据,包括图片以及序列化对象,一个键最大能存储512MB。
List列表:简单的字符串列表,按照插入顺序排序,可以从两段进行添加,类似于双向链表,列表还可以进行阻塞。
Hash散列表:一个String类型的key和value的映射表,hash特别适合存储对象,类比python字典。
Set集合:字符串类型的无序且不重复集合。集合是通过哈希表实现,所以添加、删除、查找的时间复杂度都是O(1)。
Zset有序集合:zset和set一样,不同的是每个元素会关联一个double类型的分数,redis正是通过对分数的排序对集合进行有序存储。
5、Redis安装和启动
(1)Redis安装
$ wget http://download.redis.io/releases/redis-5.0.2.tar.gz $ tar xzf redis-5.0.2.tar.gz $ cd redis-5.0.2 $ make # 编译redis程序
(2)Redis启动
一般启动reids-server都需要结合配置文件来启动。这样在配置文件中的配置就会生效在启动的redis服务中。
$ pwd /Users/hqs/redis-5.0.2 $ src/redis-server redis.conf # 启动redis服务 # 启动新终端,使用内置的客户端与redis进行交互 $ pwd /Users/hqs/redis-5.0.2 $ src/redis-cli 127.0.0.1:6379> set name 'bobo' OK 127.0.0.1:6379> get name "bobo"
6、Redis配置
可以通过redis-cli进入交互模式,使用config命令查看或设置配置项。也可以进入配置文件用vim编辑器进行修改。
# 获取所有配置项 reids 127.0.0.1:6379> config get * # 获取单个配置项 redis 127.0.0.1:6379> config get loglevel # 编辑配置 redis 127.0.0.1:6379> config set loglevel "notice"
二、python操作Redis
首先需要下载安装redis模块:pip3 install redis
Redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令。
Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。
Redis连接实例是线程安全的,可以直接将redis连接实例设置为一个全局变量,直接使用。
如果需要另一个Redis实例(or Redis数据库)时,就需要重新创建redis连接实例来获取一个新的连接。
连接redis,加上decode_response=True,写入的键值对中的value为str类型,不加这个参数写入的则为字节类型。
1、Redis模块Redis类源码
class Redis(object): def __init__(self, host='localhost', port=6379, db=0, password=None, socket_timeout=None, socket_connect_timeout=None, socket_keepalive=None, socket_keepalive_options=None, connection_pool=None, unix_socket_path=None, encoding='utf-8', encoding_errors='strict', charset=None, errors=None, decode_responses=False, retry_on_timeout=False, ssl=False, ssl_keyfile=None, ssl_certfile=None, ssl_cert_reqs='required', ssl_ca_certs=None, max_connections=None, single_connection_client=False, health_check_interval=0):
默认host是'localhost',默认端口是6379。db以数字呈现,默认值是0,配置了16个db,可以通过配置db来切换到对应的数据库,相当于对内存中的大redis进行分块。
password是数据库密码,socket_timeout是超时时间,socket_connect_timeout是连接超时数。
connection_pool是连接池,max_connection是最大连接数。
decode_responses很重要,默认值是False,若改为True,则从redis取出的值都是字符串。
2、Redis连接
import redis """ conn = redis.Redis(host='127.0.0.1', port=6379) # 设置值 conn.set("n1", "v1") conn.hset("n2", "k2", "v2") ret1 = conn.get('n1') ret2 = conn.hget('n2', 'k2') print(ret1, ret2) # 输出:b'v1' b'v2' """ conn = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True) # 设置值 conn.set("n1", "v1") conn.hset("n2", "k2", "v2") ret1 = conn.get('n1') ret2 = conn.hget('n2', 'k2') print(ret1, ret2) # 输出:v1 v2
Redis set命令用于在redis中设置值,不存在则创建,存在则修改。
Redis hset命令用于在哈希表中字段赋值。不存在则创建新的哈希表,已存在于哈希表中旧值被覆盖。
Redis get 命令用于获取指定 key 的值。返回key的值。如果 key 不存在,返回 nil 。如果key 储存的值不是字符串类型,返回一个错误。
Redis hget 命令用于返回哈希表中指定字段的值。返回给定字段的值。如果给定字段或key不存在,返回nil。
3、hset与hmset、hget与hgetall命令对比
Redis Hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。此命令会覆盖哈希表中已存在的字段。如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。
import redis conn = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True) conn.hmset("n3", {"k3": "v3", "k4": "v4"}) # 单条单条取 ret3 = conn.hget("n3", "k3") ret4 = conn.hget("n3", "k4") print(ret3, ret4) # v3 v4 # 全取 ret5 = conn.hgetall("n3") print(ret5) # {'k3': 'v3', 'k4': 'v4'}
三、Redis基本命令
Redis命令十分丰富,包括的命令组有Cluster、Connection、Geo、Hashes、HyperLogLog、Keys、Lists、Pub/Sub、Scripting、Server、Sets、Sorted Sets、Strings、Transactions一共14个redis命令组两百多个redis命令。
Redis命令大全:http://www.redis.cn/commands.html
四、redis连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。
默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池
import redis pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True, max_connections=10) # 最大连接数 conn = redis.Redis(connection_pool=pool) ret = conn.get("n1") print(ret) # 输出:v1
如果想要并发操作,就需要写成单例,以模块导入就是一个单例,把他做成单例,写在一个文件里面,import它就是一个单例。
五、resdis发布订阅者模型
Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分:发布者、订阅者和Channel。
发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。
Redis的这种发布订阅机制与基于主题的发布订阅类似,Channel相当于主题。
1、发布者(pub.py)
redis采用publish命令发送消息,其返回值是接收到该消息的订阅者的数量。
import redis # 创建连接 conn = redis.Redis(host="127.0.0.1", port=6379, decode_responses=True) # 创建发布者 conn.publish('hqs', 'Hello world!!')
2、订阅者(sub.py)
redis采用subscribe命令订阅某频道,返回值包含客户端订阅的频道、目前已订阅的频道数量、接收到的消息(subscribe表示已经成功订阅某频道)。
import redis # 创建连接 conn = redis.Redis(host="127.0.0.1", port=6379, decode_responses=True) # 第一步:生成一个订阅者对象 pubsub = conn.pubsub() # 第二步:订阅一个消息(实质就是监听这个键) pubsub.subscribe('hqs') # 第三步:死循环一直等待监听结果 while True: print("working~~~~") msg = pubsub.parse_response() print(msg)
3、测试发布订阅者模式
先执行生成三个订阅者:
再用发布者发布消息,订阅者输出如下:
六、更多资料