安装说明
业务需求分析
Windows平台:Redis版本老旧,且为微软开发维护,但便于使用以及记录笔记;
虚拟机解决方案:吃电脑性能,但既能写笔记,网页在线,不支持typora,也能直接同时使用IDE;
服务器解决方案:vim写python代码,开两个页面同时开启redis;缺点:无图形化界面,性能占用最低;
双系统方案:物理机满血性能;网页在线笔记,图形化以及双应用同开;缺点:失去社交交互;
成本分析:
虚拟机需要软件本身以及CentOS镜像,下载安装周期最长;物理机省却虚拟机安装时间,成本次之;服务器仅需要安装Redis,成本最低;
4.2 redis的连接方式
授课笔记:
[Redis数据库]:redis数据库基础篇 - Mr·Yuan - 博客园 (cnblogs.com)
临时连接
import redis# 01 基本连接方式r = redis.Redis(host="127.0.0.1", port=6379)r.set("age", 99)print(r.get("age")) # b'99'
连接池—持久化连接
# 02 连接池,类似于QuerySetpool = redis.ConnectionPool(host="127.0.0.1", port=6379)r = redis.Redis(connection_pool=pool)
4.3Redis的字符串操作
set的第三个参数-设置过期时间

set的第五个参数[条件存储->键]
r.set("info", "Alex", 5, nx=True)print(r.get("info"))

set第四个参数px毫秒过期
r.set("info", "Alex", px=10000)print(r.get("info"))

set第五个参数xx
r.set("info", "Alex", xx=True)print(r.get("info"))

批量写入—逐个读取
r.mset({'k1': 'v1', 'k2': 'v2'})print(r.get("k1"))

批量写入[mset]批量读出[mget]
r.mset({'k1': 'v1', 'k2': 'v2'})print(r.mget("k1", "k2"))

getrange对键切片
r.set("info", "Alex")print(r.getrange("info", 0, 2))

setrange切片并且替换
setrange(self, name, offset, value) # offset 开端 也就是开始替换的起始点,这个位置取得到,请观察输出r.set("info", "Alex")r.setrange("info", 1, "wesome")print(r.get("info"))


incr自增加1类似与 +=1 & ++
# 数字与字符串均视为字符串r.set("age", "100")r.set("range", 99)r.incr("age")print(r.get("age"))print(r.get("range"))

incr自增加1类似与 -=1 & –
r.set("age", "100")r.set("range", 99)r.decr("age")print(r.get("age"))print(r.get("range"))

append 追加 类似于 字符串拼接 比较于 setrange 无需指定起始点
r.set("info", "Alex")print(r.get("info"))r.append("info", " & Egon")print(r.get("info"))

4.7redis 有序集合操作
1 添加以及查询语句
r.zadd("z", {"n1":1, "n2":2, "n3":5, "n4":4})print(r.zscan("z"))(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])# 0 指的是游标的位置,迭代时可能用到;
2 一般计数
计算总数
r.zadd("z", {"n1":1, "n2":2, "n3":5, "n4":4})print(r.zscan("z"))# 对有序集合计数,统计键值对的数量print(r.zcard("z"))(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])4
对区间内键计数—[按照值的方式]
r.zadd("z", {"n1":1, "n2":2, "n3":5, "n4":4})print(r.zscan("z"))# 对有序集合计数,统计键值对的数量print(r.zcount("z", 1, 3))(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])2
3 对集合-键值对中的值进行自增[指定键的方式]
r.zadd("z", {"n1":1, "n2":2, "n3":5, "n4":4})print(r.zscan("z"))# 对有序集合计数,统计键值对的数量r.zincrby("z", 2, "n3")print(r.zscan("z"))# 对有序集合计数,统计键值对的数量(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 7.0)])
4 按照位序取键
r.zadd("z", {"n1":1, "n2":2, "n3":5, "n4":4})print(r.zscan("z"))# 对有序集合计数,统计键值对的数量print(r.zrange("z", 0, 2))"""输出(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])[b'n1', b'n2', b'n4']"""'''参数说明:name redis的namestart 有序集合索引起始位置end 有序集合索引结束位置desc 排序规则,默认按照分数从小到大排序withscores 是否获取元素的分数,默认只获取元素的值score_cast_func 对分数进行数据转换的函数'''
5 获取键的排序
r.zadd("z", {"n1":1, "n2":2, "n3":5, "n4":4})print(r.zscan("z"))print(r.zrank("z", "n4"))"""输出:(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])2"""
6 按照键删除键值对
print(r.zscan("z"))r.zrem("z", "n2")print(r.zscan("z"))'''输出(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])(0, [(b'n1', 1.0), (b'n4', 4.0), (b'n3', 5.0)])'''
6.1 按照[键的索引值]排名删除
print(r.zscan("z"))r.zremrangebyrank("z", 0, 1)print(r.zscan("z"))'''输出:(0, [(b'n1', 1.0), (b'n4', 4.0), (b'n3', 5.0)])(0, [(b'n3', 5.0)])'''
6.2 按照值的大小删除
print(r.zscan("z"))r.zremrangebyscore("z", 0, 3)print(r.zscan("z"))'''输出:(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 4.0), (b'n3', 5.0)])(0, [(b'n4', 4.0), (b'n3', 5.0)])'''
7 求并集
r.zadd("z1", {"n1": 1, "n2": 2, "n3": 5, "x": 100})r.zadd("z2", {"n3": 4, "n4": 5, "n5": 6, "x": 100})r.zunionstore("z3", ("z1", "z2"))print(r.zscan("z3"))'''output:(0, [(b'n1', 1.0), (b'n2', 2.0), (b'n4', 5.0), (b'n5', 6.0), (b'n3', 9.0), (b'x', 200.0)])'''
8 求交集
r.zadd("z5", {"n1": 1, "n2": 2, "n3": 5, "x": 100})r.zadd("z6", {"n3": 4, "n4": 5, "n5": 6, "x": 100})r.zinterstore("z4", ("z5", "z6"))print(r.zscan("z4"))'''output:(0, [(b'n3', 9.0), (b'n4', 10.0), (b'n5', 12.0), (b'x', 200.0)])'''
4.8 Redis 的其他操作
获取所有的键
print(r.keys())
对键正则匹配
print(r.keys(pattern="k*"))
删除键
print(r.delete())
判断键是否存在[存在为1,不存在为0]
print(r.exists(""))
对键值对设置过期时间
r.expire("range",10)print(r.keys())----------------------[b'z10', b'z3', b'z0', b'z2', b'z5', b'z1', b'z7', b'z', b'k2', b'z4', b'k1', b'info', b'age', b'z6']----------------------[b'z10', b'z3', b'z0', b'z2', b'z5', b'z1', b'z7', b'z', b'k2', b'z4', b'k1', b'age', b'z6']
随机获取一个键
print(r.randomkey())print(r.keys())---------------------------b'z6'[b'z10', b'z3', b'z0', b'z2', b'z5', b'z1', b'z7', b'z', b'k2', b'z4', b'k1', b'age', b'z6']
获取某个键的数据类型
print(r.type("age"))print(r.keys())-----------------------b'string'[b'z10', b'z3', b'z0', b'z2', b'z5', b'z1', b'z7', b'z', b'k2', b'z4', b'k1', b'age', b'z6']
生成器批量获取键
for i in r.scan_iter(match="k*"):print(i)---------------------------------b'k2'b'k1'
应用场景
1. String1. 这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存,比如减少库存。2. 电商库存,利用redis一个特性,单线程无并发;存储JSON字符串2. hash1. 这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。2. 博主在做单点登录的时候就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。3. list1. 使用List的数据结构,可以做简单的消息队列的功能。2. 可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。3. 本人还用一个场景,很合适---取行情信息。就也是个生产者和消费者的场景。LIST可以很好的完成排队,先进先出的原则。4. set1. 因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。2. 另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。用户偏好建模5. sorted set1. sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。
4.7 管道
# 前者是原子性事务,两个创建事务必须同时成功,也就是同进同退pipe = r.pipeline(transaction=True)pipe.set('name', 'Alex')pipe.set('role', 'SB')pipe.execute()print(r.keys())------------------------------------# 正常的顺序执行,两个语句不会唇齿相依,报错不影响前序代码的执行r.sadd("mysql", 'I')xxxxxr.sadd("How", 'You')
4.8 订阅
基本概念
Redis数据库的特性:多个用户订阅一个键时,当键的值更新,所有用户都可以收到这个更新后的值
类似于微博大V更新,推送给所有粉丝,但由于有些粉丝不在线,因此就投入消息队列,在线后再推送,服务器负载就会降低;
consumer
import redisr = redis.Redis(host='127.0.0.1')pub = r.pubsub()pub.subscribe("fm104.5")pub.parse_response()while 1:msg = pub.parse_response()print(msg)
producer
import redisr = redis.Redis(host='127.0.0.1')r.publish("fm104.5", "Hi Alex")
实现效果

