1.Redis的介绍
- Redis是一种非关系型数据库 ,是一个高性能的key-value数据库 ,设置的值也是以键值对存在的
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis还支持数据备份
- Redis的所有操作都是原子性的
- Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted
set:有序集合)。
2.Redis的基本使用
01.启动和关闭
reids端口:6379
-
启动服务器
redis-server
-
启动客户端
本地登录:
redis-cli
远程登陆:
redis-cli -h 127.0.0.1 -p 6379
查看连接状况:
ping
-
多数据库
Redis默认支持16个数据库,从0开始的递增数字命名:0-15
select来选择使用哪个数据库:select 1
-
关闭
redis-cli shutdown
断开连接: quit
3.基本命令
01.设置键和值
SET key values # 设置单个
MSET key values key values # 可以同时设置多个
02.获取符合规则的键名列表
通过KEYS patten 来获取key所对应的value
keys * # 获取所有键
get bar # 存在返回对应的value,没有则返回nil,表示空的意思
mget bar1 bar2 # 同时获取多个值
key m*
key m?
03.判断一个键是否存在
exists bar # 键存在返回1,否则返回0
04.键的重命名
rename key new_key
符号 | 含义 |
---|---|
? | 匹配一个字符 |
* | 匹配任意个(包括0个)字符 |
[] | 匹配括号间的任一字符,可以使用“-”符号表示一个范围,如a[b-d],可以匹配:ab,ac,ad |
\x | 匹配字符x,用于转义字符。如要匹配“?”就需要使用? |
05.设置key过期时间
1.设置:
expire key seconds
expire key value ex seconds
setex key secondes value 将值value关联到key,并将key的过期时间设置为secondes(以秒为单位)
例子:
set bar abc
expire bar 10000
set bar 123 ex 2000
setex name 5 “panlifu”
2.获取key还剩余的时间,-1表示永久,-2表示不存在
ttl bar
3.让键重新变成永久,成功返回1,否则返回0,表示键不存在或着本身就是永久的
persist bar
06.获取键的数据类型-适用5种数据类型
type key # Redis中有5中数据类型
07.删除键
del key [key …] 可以删除一个或多个键,返回值是删除的键的个数
del命令的参数不支持通配符,但可以结合linux的管道和xargs命令自己实现删除所有符合规则的键。
比如要出上所有以user开头的键:
redis-cli keys “user*” | xargs redis-cli del
另外用于del命令支持多个键作为参数,这个性能更好:
redis-cli del redis-cli keys “user*”
08.清空所有数据
Redis数据库之间并不是完全隔离的,比如flushall命令可以清空一个Redis实例中所有数据库中的数据
4.数据类型
01.string-字符串
-
设置
set num 123
mset num1 123 num2 123
getset key value # 将给定key的值设为value,并返回key的旧值(old value)
setex key secondes value # 将值value关联到key,并将key的过期时间设置为secondes(以秒为单位)
set name panlifu ex 6
setnx key value # 只有在key不存在时设置key的值
setrange key offset value # 用value参数覆写给定key所存储的字符串值,从偏移量offset开始
mset key value [key value] # 同时设置一个或者多个key -value对
-
获取
get num
mget num1 num2
getrange key start end # 返回key中字符串的子字符,类似python中的切片功能,不同在于redis顾头顾尾
strlen key # 返回 key 所储存的字符串值的长度
-
增加
incr num # 加1
incrby num 20.5 # 指定加
incrbyfloat num 1.4
append num abcd # 字符串追加
-
减少
decr num #减1
decrby num 20 # 指定减
总结:
key前面有m一般都指 可以设置多个 键值对。 键后面带nx 一般表示 只有当key不存在时,才能设置该key。
当键以ex结尾时,一般表示设置 key的过期时间,单位为秒。当键前面有p且后面有ex时,也表示设置key过期时间,单位为毫秒
string数据类型中的数据,value的数据类型都是string类型。只要string全为数字,即可使用incr键
02.list-列表
-
添加元素
#
lpush 左边添加(栈 先进后出)lpush key value [value …] # 将一个或多个值插入到列表头部
#
rpush 右边添加(队列 先进先出)rpush key value [value …] # 在列表中添加一个或多个值
rpushx key value # 为已存在的列表添加值
#
插入linsert key before|after pivot value 在列表的指定元素前或者后插入元素
lpushx key value # 将一个值插入到已存在的列表头部
#
替换lset key index value # 通过索引设置列表元素的值
-
获取列表长度
llen myli
-
查看指定位置元素
lindex myli 3
-
获取列表片段: -1表示最后一个
lrange key start stop # 获取列表指定范围内的元素
-
删除(弹出)元素
lpop key # 移出并获取列表的第一个元素
rpop key # 移除列表的最后一个元素,返回值为移除的元素。
lrem key count value
lrem myli 2 1 # 当count>0时lrem命令会从列表左边开始删除前count个值为value的元素
lrem myli -1 2 # 当count<0时lrem命令会从列表右边开始删除前|count|个值为value的元素
lrem myli 0 4 # 当count=0时lrem命令会删除所有值为value的元素
ltrim key start stop #对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
rpoplpush source destination # 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
总结:以x结尾都是判断 key是否存在,不存在就不能设置,存在才能设置。
03.hash-哈希类型
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
-
设置
hset key field value # 设置存储在哈希表中指定字段的值(只能存储一个)
hmset key field value [field value …] # 设置hash多个字段和值
hsetnx key field value # 只有在字段 field 不存在时,设置哈希表字段的值。
-
获取
hget key field # 获取存储在哈希表中指定字段的值
hmget key field [field …] # 获取哈希表中某个字段的值
hgetall key # 获取哈表表中所有字段的值及字段
hkeys key # 获取所有哈希表中的字段
hvals key # 获取哈希表中所有值
hlen key # 获取哈希表中字段的数量
-
判断字段是否存在
hexists key field # 查看哈希表中,指定的字段是否存在,存在返回1,不存在(哈希表或指定字段不存在)返回0
-
增加数字
hincrby key field increment # 为哈希表 key 中的指定字段的整数值加上增量 increment
hincrbyfloat key field increment # 为哈希表 key 中的指定字段的浮点数值加上增量 increment
-
删除字段
hdel key field [field …] # 删除一个或多个哈希表字段
del key # 删除key
-
迭代
HSCAN key cursor [MATCH pattern] [COUNT count] # 迭代哈希表中的键值对。
# 1. 查看hash表pms:1中有多少条记录 127.0.0.1:6379[1]> hgetall pms:1 1) "stock" 2) "12" 3) "freeze" 4) "10" 5) "stock:1" 6) "11" 7) "stock:2" 8) "23" 9) "stock:freeze:1" 10) "111" 11) "stock:5" 12) "1212" # 2. 模糊查看pms:1下的键 127.0.0.1:6379[1]> hscan pms:1 0 match stock:* count 100 1) "0" 2) 1) "stock:1" 2) "11" 3) "stock:2" 4) "23" 5) "stock:freeze:1" 6) "111" 7) "stock:5" 8) "1212" # 3. 模糊查看pms:1下的键 127.0.0.1:6379[1]> hscan pms:1 0 match stock* count 100 1) "0" 2) 1) "stock" 2) "12" 3) "stock:1" 4) "11" 5) "stock:2" 6) "23" 7) "stock:freeze:1" 8) "111" 9) "stock:5" 10) "1212" # 4. 模糊查看pms:1下的键 127.0.0.1:6379[1]> hscan pms:1 0 match stock:freeze:* count 100 1) "0" 2) 1) "stock:freeze:1" 2) "111" # 5. 查看有多少个键 127.0.0.1:6379[1]> keys * 1) "pms:1" 2) "pms:freeze:21" 3) "pms:10" 4) "pms:11" 5) "pms:9" 6) "pms:4" 7) "name" 8) "pms:5" 9) "pms:8" 10) "pms:7" 11) "pms:2" 12) "go:123" 13) "pms:3" 14) "pms:6" # 6. 模糊查找pms:*的键 127.0.0.1:6379[1]> scan 0 match pms:* count 10 1) "3" 2) 1) "pms:1" 2) "pms:8" 3) "pms:freeze:21" 4) "pms:5" 5) "pms:11" 6) "pms:9" 7) "pms:4" 8) "pms:3" 9) "pms:6" # 7. 模糊查找pms:*的键,游标从3开始 127.0.0.1:6379[1]> scan 3 match pms:* count 10 1) "0" 2) 1) "pms:10" 2) "pms:7" 3) "pms:2
04.Set-无序集合
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
-
增加
sadd key member [member …] # 向集合添加一个或多个成员
-
获取
smembers key # 获取一个key对应的集合元素
scard key # 获取集合的成员数
srangemember key [count] # 返回集合中一个或多个随机数
-
判断
sismember key member # 判断 member 元素是否是集合 key 的成员
-
移动元素到另一个集合中
smove source destination member # 将 member 元素从 source 集合移动到 destination 集合
-
删除元素
spop key # 移除并返回集合中的一个随机元素
spop key num # 移除并返回集合中的num个随机元素
srem key member1 [member2] # 移除集合中一个或多个成员
-
交集
sinter key1 [key2] # 返回给定所有集合的交集
sinterstore destination key1 [key2] # 返回给定所有集合的交集并存储在 destination 中
-
并集
sunion key1 [key2] # 返回所有给定集合的并集
sunionstore destination key1 [key2] # 所有给定集合的并集存储在 destination 集合中
-
差集
sdiff key1 [key2] # 返回给定所有集合的差集
sdiffstore destination key1 [key2] # 返回给定所有集合的差集并存储在 destination 中
-
迭代
sscan key cursor [MATCH pattern] [COUNT count] # 迭代集合中的元素
redis 127.0.0.1:6379> SADD myset1 "hello" (integer) 1 redis 127.0.0.1:6379> SADD myset1 "hi" (integer) 1 redis 127.0.0.1:6379> SADD myset1 "bar" (integer) 1 redis 127.0.0.1:6379> sscan myset1 0 match h* 1) "0" 2) 1) "hello" 2) "h1"
05.zset-有序集合
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
存–ZADD key [NX|XX] [CH] [INCR] score member [score member …]
- XX: 仅仅更新存在的成员,不添加新成员。
- NX: 不更新存在的成员。只添加新成员。
- CH: 修改返回值为发生变化的成员总数,原始是返回新添加成员的总数 (CH 是 changed 的意思)。更改的元素是新添加的成员,已经存在的成员更新分数。 所以在命令中指定的成员有相同的分数将不被计算在内。注:在通常情况下,
ZADD
返回值只计算新添加成员的数量。- INCR: 当
ZADD
指定这个选项时,成员的操作就等同ZINCRBY命令,对成员的分数进行递增操作。取–ZRANGE key start stop [WITHSCORES]
-
增加/修改(更新)
zadd key score1 member1 [score2 member2] # 向有序集合添加一个或多个成员,或者更新已存在成员的分数
-
修改分数
zincrby key increment member # 有序集合中对指定成员的分数加上增量 increment
-
获取
获取成员:
zrange key start stop [WITHSCORES] # 通过索引区间返回有序集合成指定区间内的成员,0表示最前一个,-1表示最后一个
例子:ZRANGE salary 0 -1 WITHSCORES # 显示整个有序集及成员的 score 值,# 递增排列
zrangebylex key min max [LIMIT offset count] # 通过字典区间返回有序集合的成员
例子:ZRANGEBYLEX myzset - [c
ZRANGEBYLEX myzset - (c
ZRANGEBYLEX myzset [aaa (g
zrangebyscore key min max [WITHSCORES] [LIMIT] # 通过分数返回有序集合指定区间内的成员
例子:ZRANGEBYSCORE salary -inf +inf # 显示整个有序集
ZRANGEBYSCORE salary (5000 400000 # 显示工资大于 5000 小于等于 400000 的成员
zrevrange key start stop [WITHSCORES] # 返回有序集中指定区间内的成员,通过索引,分数从高到底
例子:ZREVRANGE salary 0 -1 WITHSCORES # 递减排列
zrevrangebyscore key max min [WITHSCORES] # 返回有序集中指定分数区间内的成员,分数从高到低排序
获取成员数:
zcard key # 获取有序集合的成员数
zcount key min max # 计算在有序集合中指定区间分数的成员数
zlexcount key min max # 在有序集合中计算指定字典区间内成员数量
例子:zlexcount myzset - + # 返回全部成员数量
zlexcount myzset [b [f # 返回切片闭区间[b,f]中的数量
获取成员索引:
zrank key member # 返回有序集合中指定成员的索引
获取排名:
zrevrank key member # 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
获取分数值:
zscore key member # 返回有序集中,成员的分数值
-
删除
zrem key member [member …] # 移除有序集合中的一个或多个成员
ZREM page_rank non-exists-element # 移除不存在元素
-
交集
zinterstore destination numkeys key [key …] # 计算给定的numkeys个有序集的交集并将结果集存储在新的有序集合 key 中
zremrangebylex key min max # 移除有序集合中给定的字典区间的所有成员: ZREMRANGEBYLEX myzset [alpha [omega
zremrangebyrank key start stop # 移除有序集合中给定的排名区间的所有成员: 闭区间
zremrangebyscore key min max 移除有序集合中给定的分数区间的所有成员: 闭区间
-
并集
zunionstore destination numkeys key [key …] 计算给定的一个或多个有序集的并集,并存储在新的 key 中
-
迭代
zscan key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)
5.*列表类型与有序集合区别
有序集合类型在某些方面和列表类型有些相似。
(1)二者都是有序的。
(2)二者都可以获得某一范围的元素。
但是二者有着很大的区别,这使得它们的应用场景也是不同的。
(1)列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,所以它更加适合实现如“新鲜事”或“日志”这样很少访问中间元素的应用。
(2)有序集合类型是使用散列表和跳跃表(Skip list)实现的,所以即使读取位于中间部分的数据速度也很快(时间复杂度是O(log(N)))。
(3)列表中不能简单地调整某个元素的位置,但是有序集合可以(通过更改这个元素的分数)。
(4)有序集合要比列表类型更耗费内存。有序集合类型算得上是 Redis的5种数据类型中最高级的类型了,在学习时可以与列表类型和集合类型对照理解。
6.python与redis交互
01.redis模块的使用
1.安装模块
pip3 install redis -i https://pypi.douban.com/simple
2.导入模块
import redis
3.连接方式
- 严格连接模式:r=redis.StrictRedis(host="",port=)
- 更Python化的连接模式:r=redis.Redis(host="",port=)
- StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令
- Redis与StrictRedis的区别是:Redis是StrictRedis的子类,用于向前兼容旧版本的redis-py,并且这个连接方式是更加"python化"的
4.连接池
为了节省资源,减少多次连接损耗,连接池的作用相当于总揽多个客户端与服务端的连接,当新客户端需要连接时,只需要到连接池获取一个连接即可,实际上只是一个连接共享给多个客户端。
import redis
pool= redis.ConnectionPool(host='localhost',port=6379,decode_responses=True)
r=redis.Redis(connection_pool=pool)
r2=redis.Redis(connection_pool=pool)
r.set('apple','a')
print(r.get('apple'))
r2.set('banana','b')
print(r.get('banana'))
print(r.client_list())
print(r2.client_list())#可以看出两个连接的id是一致的,说明是一个客户端连接
5.操作
-
值的设置和获取,可以参考redis的命令,redis模块中的对应功能的函数名基本与redis中的一致
-
【注意默认情况下,设置的值或取得的值都为bytes类型,如果想改为str类型,需要在连接时添加上decode_responses=True】
-
设置值:
- redis中set() ==>r.set()
- redis中setnx() ==>r.set()
- redis中setex() ==>r.setex()
- redis中setbit() ==>r.setbit()
- redis中mset() == > r.mset()
- redis中hset() ==>r.hset()
- redis中sadd() == >r.sadd()
- 其他。。。基本redis的命令名与redis模块中的函数名一致
-
获取:
- redis中get() ==》r.get()
- redis中mget() ==》r.mget()
- redis中getset() ==》r.getset()
- redis中getrange() ==》r.getrange()
- 其他。。。基本redis的命令名与redis模块中的函数名一致
import redis
r=redis.Redis(host='localhost',port=6379,decode_responses=True)
# r=redis.StrictRedis(host='localhost',port=6379)
r.set('key','value')
value=r.get('key')
# print(type(value))
print(value)
r.hset('info','name','lilei')
r.hset('info','age','18')
print(r.hgetall('info'))
r.sadd('course','math','english','chinese')
print(r.smembers('course'))
02.管道
一般情况下,执行一条命令后必须等待结果才能输入下一次命令,管道用于在一次请求中执行多个命令。
参数介绍:
- transaction:指示是否所有的命令应该以原子方式执行。
import redis,time
r=redis.Redis(host="localhost",port=6379,decode_responses=True)
pipe=r.pipeline(transaction=True)
pipe.set('p1','v2')
pipe.set('p2','v3')
pipe.set('p3','v4')
time.sleep(5)
pipe.execute()
03.事务
python中可以使用管道来代替事务:
- 补充:监视watch:pipe.watch()
import redis,time
import redis.exceptions
r=redis.Redis(host='localhost',port=6379,decode_responses=True)
pipe=r.pipeline()
print(r.get('a'))
try:
# pipe.watch('a')
pipe.multi()
pipe.set('here', 'there')
pipe.set('here1', 'there1')
pipe.set('here2', 'there2')
time.sleep(5)
pipe.execute()
except redis.exceptions.WatchError as e:
print("Error")
04.订阅/发布
- 发布方:
import redis
r=redis.Redis(host="localhost",port=6379,decode_responses=True)
#发布使用publish(self, channel, message):Publish ``message`` on ``channel``.
Flag=True
while Flag:
msg=input("主播请讲话>>:")
if len(msg)==0:
continue
elif msg=='quit':
break
else:
r.publish('cctv0',msg)
import redis
r=redis.Redis(host="localhost",port=6379,decode_responses=True)
#发布使用publish(self, channel, message):Publish ``message`` on ``channel``.
Flag=True
chan=r.pubsub()#返回一个发布/订阅对象
msg_reciver=chan.subscribe('cctv0')#订阅
msg=chan.parse_response()#第一次会返回订阅确认信息
print(msg)
print("订阅成功,开始接收------")
while Flag:
msg=chan.parse_response()#接收消息
print(">>:",msg[2])#此处的信息格式['消息类型', '频道', '消息'],所以使用[2]来获取