Redis Server 版本 6.0.5
Python Redis 版本 3.5.3
Python 版本 3.8
import redis
redis.VERSION
结果:(3, 5, 3)
r = redis.Redis(host='localhost', port=32779, decode_responses=True, password='XXXXXXXXX', db=2) # host是redis主机,需要redis服务端和客户端都启动 redis默认端口是6379 r.set('name', 'tabll', ex=500) # key是"foo" value是"bar" 将键值对存入redis缓存 print(r['name']) print(r.get('name')) # 取出键name对应的值 print(type(r.get('name')))
结果: tabll tabll <class 'str'>
r.info
结果:<bound method Redis.info of Redis<ConnectionPool<Connection<host=localhost,port=32779,db=2>>>>
键值对
r.set('name', 'tabll', ex=500)
结果:True
r.exists('name')
结果:1
r.delete('name')
结果:1
r.get('name')
批量键值对
r.set('name1', 'tabll1', ex=500) r.set('name2', 'tabll2', ex=500)
结果:True
r.mget(['name1', 'name2']) # 批量获取键值对
结果:['tabll1', 'tabll2']
r.mset({'name3' : 'tabll3', 'name4' : 'tabll5'}) # 批量设置键值对
结果:True
r.mget(['name3', 'name4']) # 批量获取键值对
结果:['tabll3', 'tabll5']
r.delete('name1')
结果:1
过期和 SET 拓展
r.expire('name', 5) # 设置过期时间为 5 秒
结果:False
r.get('name')
r.setnx('name', 'tabll2') ## 如果 name 不存在则创建
结果:True
计数
r.set('counter', 1)
结果:True
r.incr('counter') # 自增 1
结果:2
r.incrby('counter', 5) # 自增 5
结果:7
r.set('maxcounter', 9223372036854775807, ex=50)
结果:True
#r.incr('maxcounter') # 会报错,超出了最大值 它的范围是 signed long 的范围
列表 LinkedList
弹出最后一个元素后自动回收内存
队列
右边进左边出
r.rpush('books', '123')
结果:1
r.llen('books') # 队列长度
结果:1
r.lpop('books') # 取出
结果:'123'
栈
右边进右边出
r.rpush('books', '123')
结果:1
r.llen('books') # 队列长度
结果:1
r.rpop('books') # 取出
结果:'123'
慢操作
r.rpush('books', 'php') r.rpush('books', 'python') r.rpush('books', 'java')
结果:3
r.lindex('books', 1) # 复杂度 O(n) 慎用
结果:'python'
r.lrange('books', 0, -1) # 显示范围内数据 复杂度 O(n) 慎用
结果:['php', 'python', 'java']
r.ltrim('books', 1, -1) # 截取保留范围内数据 复杂度 O(n) 慎用
结果:True
r.lrange('books', 0, -1)
结果:['python', 'java']
r.ltrim('books', 1, 0)
结果:True
r.llen('books')
结果:0
快速列表 QuickList
列元素较少时是压缩列表
(ZipList),使用一块连续的内存存储,所有元素彼此紧挨
数据量多时才会改成快速列表
(QuickList),因为普通链表需要的附加指针空间太大,加重内存碎片化,浪费空间
QuickList
其实就是多个 ZipList
像糖葫芦一样串起来的
字典 Hash
无序字典,是 数组
+ 链表
的二维结构,第一维 hash
的数组位置碰撞时,会将碰撞的元素用链表串联起来
ReHash 操作
使用渐进式 rehash
策略
保留新旧两个 hash,途中查询时同时查询两个 hash 结构,结束后只保留新的
优点,和字符串比可以部分读取,缺点,和字符串比存储消耗大
r.hset('books', 'java', 'this is java') r.hset('books', 'php', 'this is php') r.hset('books', 'python', 'this is python')
结果:1
r.hgetall('books')
结果:{'java': 'this is java', 'php': 'this is php', 'python': 'this is python'}
r.hlen('books')
结果:3
r.hget('books', 'php')
结果:'this is php'
r.hset('books', 'php', 'this is new php') # 更新操作返回 0
结果:0
r.hget('books', 'php')
结果:'this is new php'
hmset 在 Redis 4.0 版本被弃用:
r.hmset('books', {'java' : 'java', 'php' : 'php'}) # 不推荐使用 复杂度 O(n) 慎用
结果: <ipython-input-41-1d4d1284b692>:1: DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. r.hmset('books', {'java' : 'java', 'php' : 'php'}) # 不推荐使用 复杂度 O(n) 慎用 True
r.hget('books', 'php')
结果:'php'
r.hset('user-tabll', 'age', 17) # 新增返回 1,修改返回 0
结果:0
r.hincrby('user-tabll', 'age', 2) # 自增使用 hincrby
结果:19
集合 Set
内部键值对无序
且唯一
有去重功能,可以保证统一用户不会中奖两次
r.delete('books')
结果:1
r.sadd('books', 'python')
结果:1
r.sadd('books', 'python') # 重复项则返回 0
结果:0
r.sadd('books', 'php', 'c') # 新增了几个就返回几
结果:2
r.smembers('books') # 无序,与插入顺序无关
结果:{'c', 'php', 'python'}
r.sismember('books', 'c') # 查询某个 value 是否存在
结果:True
r.scard('books') # 获取总个数
结果:3
r.spop('books') # 弹出一个
结果:'c'
r.spop('books')
结果:'python'
r.delete('books')
结果:1
有序列表 ZSet
一方面是一个 Set,另一方面它每个值有一个 score
,表示这个值的排序权重
内部实现使用的是一个叫做跳跃列表
的数据结构
r.zadd('books', {'php 666': 6.6})
结果:1
r.zadd('books', {'java 666': 6.7, 'c 666': 6.8})
结果:2
r.zrange('books', 0, -1) # 列出区间内的列表
结果:['php 666', 'java 666', 'c 666']
r.zrevrange('books', 0, -1) # 倒序列出区间内的列表
结果:['c 666', 'java 666', 'php 666']
r.zcard('books') # 计算个数
结果:3
r.zscore('books', 'php 666') # 获取指定 value 的 score (可能存在有精度问题)
结果:6.6
r.zrank('books', 'c 666') # 获取排名 (分数低的在前)
结果:2
r.zrangebyscore('books', 6.6, 6.7) # 根据分值区间列出 [6.6, 6.7]
结果:['php 666', 'java 666']
r.zrem('books', 'php 666') # 移除
结果:1
r.delete('books')
结果:1
跳跃列表
相当于多层级的金字塔
可以类似于:亚洲->中国->浙江省->杭州市->上城区->中华路->XX号