title: Python redis 使用介绍subtitle: redis初探
date: 2021-03-27
author: NSX
catalog: true
tags:
- redis
Redis 简介
REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
Redis 优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
安装 redis 模块
Python 要使用 redis,需要先安装 redis 模块:
sudo pip3 install redis
或
sudo python setup.py install
测试是否安装成功:
>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
'bar'
redis 提供两个类 Redis 和 StrictRedis, StrictRedis 用于实现大部分官方的命令,Redis 是 StrictRedis 的子类,用于向后兼用旧版本。
redis 取出的结果默认是字节,我们可以设定 decode_responses=True 改成字符串。
实例
import redis # 导入redis 模块
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.set('name', 'runoob') # 设置 name 对应的值
print(r['name'])
print(r.get('name')) # 取出键 name 对应的值
print(type(r.get('name'))) # 查看类型
输出结果为:
runoob
runoob
<class 'str'>
连接redis sentinel集群
https://blog.csdn.net/u012887259/article/details/102425691
示例代码
# import redis
from redis.sentinel import Sentinel
"""
1、通过访问Sentinel服务的方式,获取redis的master、slave节点信息
2、向master redis写入数据
3、从slave redis读取数据
"""
# 连接哨兵服务器(主机名也可以用域名)
sentinel = Sentinel([('192.168.196.129', 26379),
('192.168.196.132', 26379)
],
socket_timeout=0.5)
# 获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)
# 输出:('192.168.196.132', 6379)
# 获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)
# 输出:[('192.168.196.129', 6379)]
# 获取主服务器进行写入
master = sentinel.master_for('mymaster', socket_timeout=0.5, password='newpwd', db=0)
w_ret = master.set('foo', 'bar')
# 输出:True
# 获取从服务器进行读取(默认是round-roubin,随机从多个slave服务中读取数据)
slave = sentinel.slave_for('mymaster', socket_timeout=0.5, password='newpwd', db=0)
r_ret = slave.get('foo')
print(r_ret)
# 输出:bar
封装工具类方法
from redis.sentinel import Sentinel
class redisSentinelHelper():
def __init__(self,sentinel_list,service_name,password,db):
self.sentinel = Sentinel(sentinel_list,socket_timeout=0.5)
self.service_name = service_name
self.password = password
self.db = db
def get_master_redis(self):
return self.sentinel.discover_master(self.service_name)
def get_slave_redis(self):
return self.sentinel.discover_slaves(self.service_name)
def set_key(self,key,value):
master = self.sentinel.master_for(
service_name=self.service_name,
socket_timeout=0.5,
password=self.password,
db=self.db
)
return master.set(key,value)
def get_key(self,key):
slave = self.sentinel.slave_for(
service_name=self.service_name,
socket_timeout=0.5,
password=self.password,
db=self.db
)
return slave.get(key)
def _test():
# redis info
sentinel_list = [('192.168.196.129', 26379),('192.168.196.132', 26379)]
password = 'newpwd'
db = 0
service_name = 'mymaster'
# create redis link
rsh = redisSentinelHelper(sentinel_list=sentinel_list,password=password,service_name=service_name,db=db)
# test set key : key1 test-insert-key1
rsh.set_key('key1','test-insert-key1')
# get key1
print(rsh.get_key('key1'))
if __name__ == '__main__':
_test()
运行如下:
D:\Python37\python3.exe D:/pythonProject/redis-test/test7.py
b'test-insert-key1'
其中,我没有把设置master节点写在初始化,而是在set key操作的时候才创建连接,主要是后续想要测试master节点变化的情况下,写入能够继续。
当然这样的话性能肯定不会很好,有很多可以根据实际情况修改的地方。
测试:当master节点切换,能否自动连续写入
当然,在sentinel执行master切点切换的过程,肯定会有些丢失,但是主要是要看切换之后,是否可以自动继续写入数据。
首先编写一个循环写入的示例
from redis.sentinel import Sentinel
class redisSentinelHelper():
def __init__(self,sentinel_list,service_name,password,db):
self.sentinel = Sentinel(sentinel_list,socket_timeout=0.5)
self.service_name = service_name
self.password = password
self.db = db
def get_master_redis(self):
return self.sentinel.discover_master(self.service_name)
def get_slave_redis(self):
return self.sentinel.discover_slaves(self.service_name)
def set_key(self,key,value):
master = self.sentinel.master_for(
service_name=self.service_name,
socket_timeout=0.5,
password=self.password,
db=self.db
)
return master.set(key,value)
def get_key(self,key):
slave = self.sentinel.slave_for(
service_name=self.service_name,
socket_timeout=0.5,
password=self.password,
db=self.db
)
return slave.get(key)
def _test():
# redis info
sentinel_list = [('192.168.196.129', 26379),('192.168.196.132', 26379)]
password = 'newpwd'
db = 0
service_name = 'mymaster'
# create redis link
rsh = redisSentinelHelper(sentinel_list=sentinel_list,password=password,service_name=service_name,db=db)
# test set key : key1 test-insert-key1
# rsh.set_key('key1','test-insert-key1')
# get key1
# print(rsh.get_key('key1'))
# loop set key
for i in range(0,1000000):
rsh.set_key('key' + str(i), i)
print(rsh.get_key('key' + str(i)))
if __name__ == '__main__':
_test()