学习总结

学习总结:
(1)​​【新闻推荐系统】(task2)mysql和pymysql使用​​ (2)【新闻推荐系统】(task2)MongoDB篇
(3)【新闻推荐系统】(task2)Redis篇(上)
(4)【新闻推荐系统】(task2)Python调用Redis

关于redis的数据类型总结:

【新闻推荐系统】(task2)Python调用Redis_redis

文章目录

  • ​​学习总结​​
  • ​​二、Python调用Redis​​
  • ​​2.1 安装Redis模块​​
  • ​​2.2 Python连接Redis​​
  • ​​(1)直连模式​​
  • ​​(2)连接池模式​​
  • ​​2.3 基本操作​​
  • ​​1. String操作​​
  • ​​2. Hash操作​​
  • ​​3. List操作​​
  • ​​4. Set操作​​
  • ​​5. SortedSet操作​​
  • ​​6. 管道操作​​
  • ​​Reference​​

二、Python调用Redis

在Python中,目前可以通过一个redis模块来实现操控Redis,下面我们简单的介绍一下关于使用redis模块。

2.1 安装Redis模块

如果是在Windows 系统,安装 redis 模块可以使用以下命令:

python -m pip install redis

如果是 Linux 系统,需要执行以下命令来安装:

sudo pip3 install redis

如果是使用Anaconda管理环境,也可以使用以下命令安装:

conda install redis

2.2 Python连接Redis

Redis模块提供了两种连接的模式:直连模式和连接词模式。

(1)直连模式

直连模式的方式简单方便,适合少量长期连接的场景。其中host参数是ip地址,如果Redis服务存在于本地,可以使用127.0.0.1,或者换成Redis服务所在的ip地址。db表示当前选择的库,其参数值可以是 0-15;如果设置连接数据库的密码,那么就需要使用password进行验证。

import redis

# 1、直连模式
r = redis.Redis(host = '127.0.0.1',
port = 6379,
db = 0,
password = '12345')
r.set('name', 'jiangyou')
print(r.get('name'))

(2)连接池模式

连接池模式是使用 connection pool(连接池)来管理 redis server 的所有连接,每个Redis实例会维护自己的连接池来管理管理对一个 redis server 所有的连接,避免每次建立,释放连接的开销。

# 2、连接池模式
pool = redis.ConnectionPool(host="127.0.0.1",
port=6379,
db=0,password="",
decode_responses=True,
max_connections=10)
r1 = redis.Redis(connection_pool=pool) # 第一个客户端访问
r2 = redis.Redis(connection_pool=pool) # 第二个客户端访问

上面的参数,​​decode_responses=True​​​ 可以使得redis取出的结果改成字符串,其默认的是字节, ​​max_connections​​参数可以设置最大连接数量,这样当有新的客户端请求连接时,只需要去连接池获取即可,这样就可以把一个连接共享给多个客服端,减少每次连接所消耗的时间以及资源。

2.3 基本操作

在Redis模块中,提供了RedisStrictRedis来支持Redis访问和操作。其中 StrictRedis 使用python基于Redis协议实现了所有官方的Redis操作命令,也就是说其实对于python操作redis的API接口和上面提到的Redis官方接口一样。因此下面我们就简单介绍一些常用的方法。

1. String操作

import redis

pool = redis.ConnectionPool(host="127.0.0.1",
port=6379,
db=0,password="",
decode_responses=True,
max_connections=10)
r = redis.StrictRedis(connection_pool=pool)

r.set('name','jiang')
r.append("name","you") # 在redis name对应的值后面追加内容

r.mset({'age':'26','home':'liaoning'})
print(r.mget('name','age','home'))
print("name 长度:%d"%r.strlen('name')) #查看ame对应值的长度

r.incrby('age',5) #数值操作 将age对应的值 加5
print(r.get('age'))
r.decrby('age',5) #数值操作 将age对应的值 减5
print(r.get('age'))
r.incrbyfloat('age',5.2) #将age对应的值 加5.2
print(r.get('age'))
r.incrbyfloat('age',-10.5) #将age对应的值 减10.5
print(r.get('age'))

r.setrange('name',5,'hahaha') # 修改字符串内容,从指定字符串索引开始向后替换。
print(r.getrange('name',0,6)) # 获取子序列(根据字节获取,非字符),闭区间

r.delete('name') #删除key

运行结果

['jiangyou', '26', 'liaoning']
name 长度:8
31
26
31.2
20.7
jiangha

2. Hash操作

【新闻推荐系统】(task2)Python调用Redis_redis_02


【新闻推荐系统】(task2)Python调用Redis_数据库_03


【新闻推荐系统】(task2)Python调用Redis_redis_04


批量操作:

【新闻推荐系统】(task2)Python调用Redis_数据库_05

import redis

pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
r = redis.StrictRedis(connection_pool=pool)

r.hset('user1','name','zhangsan') # user1对应的hash中设置一个键值对(不存在,则创建;否则,修改)
r.hset('user1','age','22') # user1对应的hash中设置一个键值对(不存在,则创建;否则,修改)
r.hincrbyfloat('user1','age',0.5) # 自增user1对应的hash中的指定key的值,不存在则创建key=amount
print(r.hmget('user1','name','age')) # 在user1对应的hash中获取多个key的值

# 一次性设置多个field和value
user_dict = {
'password':'123',
'gender':'M',
'home':'辽宁'
}
r.hmset('user1',user_dict) # 在user1对应的hash中批量设置键值对

如果按照上面的​​hmset​​​是会报错的:​​DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead.​​​所以将​​hmset()​​​改成​​hset​​即可。

【注意】Redis 4.0.0开始弃用HMSET,请使用HSET!!
添加:返回添加数量
修改数值:成功返回0
example:

Redis> HSET myhash field1 hello 
(integer)1
Redis> HSET myhash field2 world field3 goodbye
(integer)2
Redis> HSET myhash field3 goodnight
(integer)0

如果是在python上的redis则可以参考​​Stack Overflow​​:

print("user1中存在键值对的个数:%d "%r.hlen('user1')) #  获取所有数据,字典类型
print("user1中存在键值对的具体信息:%s"%r.hgetall('user1')) # 获取所有数据,字典类型
print(r.hkeys("user1")) # 获取所有fields字段
print(r.hvals("user1")) # 获取所有fields字段的values值

if r.hexists("user1","home"): # 检查user1对应的hash是否存在当前传入的home
r.hdel("user1",'home') # 将user1对应的hash中指定key的键值对删除
print("已删除该键!!!")
else:
print("不存在该键!!!")

运行结果

['zhangsan', '22.5']
user1中存在键值对的个数:5
user1中存在键值对的具体信息:{'name': 'zhangsan', 'age': '22.5', 'password': '123', 'gender': 'M', 'home': '辽宁'}
['name', 'age', 'password', 'gender', 'home']
['zhangsan', '22.5', '123', 'M', '辽宁']
已删除该键!!

3. List操作

【新闻推荐系统】(task2)Python调用Redis_数据库_06


【新闻推荐系统】(task2)Python调用Redis_c++_07


【新闻推荐系统】(task2)Python调用Redis_数据库_08


【新闻推荐系统】(task2)Python调用Redis_数据库_09


【新闻推荐系统】(task2)Python调用Redis_数据库_10


【新闻推荐系统】(task2)Python调用Redis_数据库_11

import redis

pool = redis.ConnectionPool(host="127.0.0.1",
port=6379,
db=0,
password="12345",
decode_responses=True,
max_connections=10)
r = redis.StrictRedis(connection_pool=pool)

# 在database对应的list中添加元素,每个新的元素都添加到列表的最左边
r.lpush('database','sql','mysql','redis')
print(r.lrange('database',0,-1))
# ['redis', 'mysql', 'sql']
# 在database对应的列表的某一个值前或后插入一个新值,
# 其含义为在第三个参数的前(before)或后(after) 插入参数四
r.linsert('database','before','mysql','mongodb')

# 在database对应的列表分片获取数据
print(r.lrange('database',0,-1))
# ['redis', 'mongodb', 'mysql', 'sql']
# database对应的list元素的个数
print("database中元素个数:%d"%r.llen('database'))

# 在database对应的列表中根据索引获取列表元素
print("database中第2个元素:%s"%r.lindex('database',2))
# 对database对应的list中的某一个索引位置重新赋值
r.lset('database', 0, 'redisdb')
print(r.lrange('database',0,-1))

# 在database对应的列表的右侧获取第一个元素并在列表中移除,返回值则是第一个元素
print(r.rpop('database'))

# 在database对应的列表中移除没有在start-end索引之间的值
print(r.ltrim('database',0,1))

while True:
# 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧 [如果列表中为空时,则返回None]
result = r.brpop('database',1)
if result:
print(result)
else:
break
r.delete('database')

全部的运行结果:

['redis', 'mysql', 'sql']
['redis', 'mongodb', 'mysql', 'sql']
database中元素个数:4
database中第2个元素:mysql
['redisdb', 'mongodb', 'mysql', 'sql']
sql
True
('database', 'mongodb')
('database', 'redisdb')

4. Set操作

【新闻推荐系统】(task2)Python调用Redis_数据库_12


【新闻推荐系统】(task2)Python调用Redis_数据库_13

# -*- coding: utf-8 -*-
"""
Created on Sat Dec 18 23:45:47 2021

@author: 86493
"""
import redis

pool = redis.ConnectionPool(host = "127.0.0.1",
port = 6379,
db = 0,
password = "12345",
decode_responses = True,
max_connections = 10)
r = redis.StrictRedis(connection_pool = pool)

# 给name对应的集合中添加元素
r.sadd("name1", "zhangsan")
r.sadd("name1", "zhangsan", "lisi", "wangwu")

# 获取name对应的集合的所有成员
print(r.smembers('name1'))

# 获取name对应的集合中的元素个数
print(r.scard("name1") )

# 检查value是否是name对应的集合内的元素,返回值为True或False
print(r.sismember('name1','zhangsan'))

# 随机删除并返回指定集合的一个元素
print(r.spop('name1'))
print(r.smembers('name1'))

# srem(name, value)
# 删除集合中的某个元素
print(r.srem("name1", "zhangsan"))
print(r.smembers('name1'))

r.sadd("name00","a","b")
r.sadd("name11","b","c")
r.sadd("name22","b","c","d")

# 获取多个name对应集合的交集
print(r.sinter("name00","name11","name22"))

# 获取多个name对应的集合的并集
print(r.sunion("name00","name11","name22"))

# 在第一个name对应的集合中且不在其他name对应的集合的元素集合
print(r.sdiff("name00","name11","name22"))

r.flushall()

运行结果为:

{'lisi', 'wangwu', 'zhangsan'}
3
True
lisi
{'wangwu', 'zhangsan'}
1
{'wangwu'}
{'b'}
{'b', 'c', 'a', 'd'}
{'a'}

5. SortedSet操作

【新闻推荐系统】(task2)Python调用Redis_python_14

# -*- coding: utf-8 -*-
"""
Created on Sat Dec 18 23:51:57 2021

@author: 86493
"""
import redis

pool = redis.ConnectionPool(host="127.0.0.1",
port=6379,
db=0,
password="12345",
decode_responses=True,
max_connections=10)
r = redis.StrictRedis(connection_pool=pool)

mapping = {
'zhangsan':85,
'lisi':92,
'wangwu':76
}
# 在C++对应的有序集合中添加元素
r.zadd('C++',mapping,nx=True)

# 获取C++对应的有序集合的所有元素
print(r.zrange('C++',0,-1,withscores=True))

# 获取C++对应的有序集合元素的数量
print(r.zcard("C++"))

# 获取C++对应的有序集合中分数 在 [min,max] 之间的个数
print(r.zcount('C++',min=0,max=90))

# 增加C++对应的有序集合的lisi对应的分数
r.zincrby(name='C++',value='lisi',amount=3)

# 按照索引范围获取C++对应的有序集合的元素,排序规则,默认按照分数从小到大排序
print(r.zrange('C++',0,-1,desc=False,withscores=True))

# 按照索引范围获取C++对应的有序集合的元素,排序规则,默认按照分数从大到小排序
print(r.zrevrange('C++',0,-1,withscores=True))

# 按照分数范围获取C++对应的有序集合的元素,排序规则,默认按照分数从小到大排序
print(r.zrangebyscore('C++',70,90))

# 按照分数范围获取C++对应的有序集合的元素,排序规则,默认按照分数从大到小排序
print(r.zrevrangebyscore('C++',90,70))

# Zrank 返回有序集中指定成员的排名,有序集成员按分数值递增(从小到大)顺序排列。
print(r.zrank('C++','lisi'))
# Zrevrank 返回有序集中指定成员的排名,有序集成员按分数值递增(从大到小)顺序排列。
print(r.zrevrank('C++','lisi'))

mapping = {
'xuliu':74,
'lisi':82,
'wangwu':87
}
r.zadd('python',mapping,nx=True)

# 获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
r.zinterstore('sum_score_i',['C++','python'],aggregate='sum')
print(r.zrange('sum_score_i',0,-1,withscores=True))

# 获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
print(r.zunionstore('sum_score_u',['C++','python'],'min'))
print(r.zrange('sum_score_u',0,-1,withscores=True))

# 删除C++对应的有序集合中值是zhangsan的成员
r.zrem('C++', 'zhangsan')
print(r.zrange('C++',0,-1,withscores=True))

# 删除C++对应的有序集合中值是zhangsan的成员
r.zremrangebyscore('C++', min=80, max=100)
print(r.zrange('C++',0,-1,withscores=True))

# 根据排行范围删除
r.zremrangebyrank('python', min=1, max=3)
print(r.zrange('python',0,-1,withscores=True))

运行结果

[('wangwu', 76.0), ('zhangsan', 85.0), ('lisi', 92.0)]
3
2
[('wangwu', 76.0), ('zhangsan', 85.0), ('lisi', 95.0)]
[('lisi', 95.0), ('zhangsan', 85.0), ('wangwu', 76.0)]
['wangwu', 'zhangsan']
['zhangsan', 'wangwu']
2
0
[('wangwu', 163.0), ('lisi', 177.0)]
4
[('xuliu', 74.0), ('wangwu', 76.0), ('lisi', 82.0), ('zhangsan', 85.0)]
[('wangwu', 76.0), ('lisi', 95.0)]
[('wangwu', 76.0)]
[('xuliu', 74.0)]

6. 管道操作

Redis 模块默认在执行每次请求都会向连接池请求创建连接和断开申请操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作(即为一次操作)。

import redis

pool = redis.ConnectionPool(host="127.0.0.1",
port=6379,
db=0,
password="12345",
decode_responses=True,
max_connections=10)
r = redis.StrictRedis(connection_pool=pool)

pipe = r.pipeline(transaction=True)

pipe.set('name', 'jiangyou')
pipe.set('age', 'age')
pipe.execute()

print(r.mget("name","age"))
# ['jiangyou', 'age']

运行结果

['jiangyou', 'age']

Reference

(1)redis官方文档
(2)datawhale notebook
(3)​​python对redis的连接和操作​​

(4)​​聊聊 python 数据处理全家桶(Redis篇)​

(5)​​菜鸟教程-Python redis 使用介绍​