python.redis基础

和MySQL(关系型数据库代表)相比,redis(非关系型数据库)的优势在于对数据的读写,牺牲空间换时间,在内存中直接对数据进行操作,也支持把数据保存到磁盘,长期化管理;

Redis 的应用场景

  • 缓存系统:减轻数据库压力,提升系统性能(针对高频访问的数据)
  • 计数器:如网站访问量、点赞数等
  • 消息队列:利用列表类型实现简单的消息队列
  • 排行榜:利用有序集合实现各种排行榜功能
  • 会话存储:存储用户会话信息

类比:MySQL像图书馆,存量大,所有的书根据类别/编号进行严格分类摆放,获取特定的一本书需要花时间查找;redis像一个移动书柜,存量笑,但里面放的都是热门数据。

补充:Redis 的书往往是“复印件”:因为内存是易失的,如果书桌塌了(Redis 宕机/重启),里面的数据可能会丢(除非开启了 AOF/RDB 持久化)。所以,核心、不可丢失的数据一定要在 MySQL 里存一份。

在pycharm中对redis进程操作前,需要先连接redis数据库,操作过程和MySQL的连接方式类似;

具体操作(连上redis后):
使用redis.Redis()创建redis数据库连接

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,              # 数据库编号,默认0
    password=None,     # 密码,如果没有设置密码则为None
    decode_responses=True  # 自动解码,返回字符串而不是字节
)
#conn.set('height',90) #注意 此处设置key的时候必须要加上分号 否则无法正确识别
try:
    result = conn.ping()#检查是否连接成功
    conn.set('weight',500)
    print(result)
except Exception as e:
    print(f"error:{e}")

#conn.mset({'name':'changed_name','weight':20,'height':100})#使用.mset()批量修改 **kwargs传入
result = conn.mget(('weight','name')) #mget()批量查询 *args传入
print(result)

conn.setex('temp_data',60,'临时数据') #设置临时数据 超时销毁
print(conn.get('temp_data'))

在redis中,最常用的操作就两个:set()和get(),前者用于写,后者用于读;

在set和get的基础上,有很多定制化的操作,例如mset(),mget()进行批量的读写;

对于所有的set()操作,需要指定key-value写入,因此使用mset()批量写入时,需要用kwargs方式传入;对于get()操作,只需要key值,所以mget()读数据时使用args传入参数。

这里有个特殊的setex('key',last_time,'value'),用来设定数据的生命周期(临时数据,到点即过期),使用场景:验证码;

于是不得不讲一下redis中的数据生命周期管理(基础):

首先,我们使用conn.exists()检查某个key是否存在db中;

其次,我们使用conn.expire('key',last_time)来设置数据的生命周期(能存续多久),和前面的setex()不同,他是在创建这个数据的时候设定他的生命周期,而expire()方法是针对已有的数据进行操作的;当然也可以使用persist()方法移除数据的last_time,让他变回永久数据

其次是redis中的keys匹配和查找:

redis中也有类似MySQL的模糊匹配的方法,redis中使用的是‘*’作为模糊匹配符;

conn.keys('*')返回的就是该db中所有的keys

conn.keys('session:*') 模糊匹配 返回前缀是session:的keys

在redis_crud中,删除操作由conn.delete()完成,需要传入指定key;set()包揽了增/改,get()负责查

import time

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None,
    decode_responses=True
)

conn.set('test_key','test_val')
if_exist = conn.exists('test_key')
print(if_exist)
# 1
conn.expire('test_key',3)#设置过期时间 3s
print(conn.get('test_key'))
#test_val
time.sleep(1)
ttl = conn.ttl('test_key') #获取剩余存活时间
print(f"剩余时间{ttl}")
#剩余时间2
conn.persist('test_key') #移除过期,设置为永续

# 查找匹配模式的键
all_keys = conn.keys('*') #此处使用*表示匹配任意
print("所有键:", all_keys)
#所有键: ['session:123', 'session:456', 'leaderboard', 'test_key']
conn.set('session:123',123)
conn.set('session:456',456)
session_keys = conn.keys('session:*') #模糊匹配 只要求前缀是session:的keys
print("会话键:", session_keys)
#会话键: ['session:123', 'session:456']
# 删除键
conn.delete('session:123')
print("删除后是否存在:", conn.exists('session:123'))
# 删除后是否存在: 0
conn.delete('session:456')
print("删除后是否存在:", conn.exists('session:456'))
print(conn.keys('*'))
# 删除后是否存在: 0
# ['leaderboard', 'test_key']

redis数值操作

主要方法:

conn.incr('key') 使对应key的值递增(+1操作)

conn.incrby('key',num) 指定key的增量num

conn.decr('key') 使对应的key的值递减(-1操作)

conn.decrby('key') 指定key的负增量

import redis

conn = redis.Redis(
    host='localhost',
    port = 6379,
    db = 0,
    password = None,
    decode_responses=True
)

# conn.set('counts',1)
# print(conn.get('counts'))
conn.incr('counts') #递增操作 效果等于incrby(self,1)进行+1操作
print(conn.get('counts'))
conn.incrby('counts',6)
print(conn.get(('counts')))

#同理 有减法操作 decr和decrby
conn.decr('counts') #递减操作 效果等于decrby(self,1)进行-1操作
print(conn.get('counts'))
conn.decrby('counts',6)
print(conn.get(('counts')))

redis哈希操作

具体方法:

conn.hset(name:,key:,value:) # 针对name字段的单信息录入,实例中三个参数分别对应 'user001','name','aki'

conn.hmset(naem:,mapping=) #针对name字段的多信息录入,使用mapping传递键值对

注意:在新版本中.hset()也支持用mapping参数传递了,使用hset()即可完成上面的两个操作

.hgetall(name=''),.hkeys(name=''),.hvals(name=''):获取name字段下的所有信息,获取name下的所有keys,获取name下的所有values

conn.hdel(name:,*keys:) 删除name字段下的指定键值对

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None,
    decode_responses=True
)

print(conn.ping())

conn.hset('user001','name','aki') #单信息录入
conn.hmset('user001',mapping={'weight':180,'height':180})

print(conn.hkeys(name='user001'))

conn.hmset('user002',mapping={'weight':180,'height':180})

print(conn.hgetall(name='user002'))

print(conn.hvals(name='user001'))

conn.hdel('user001','height')
print(conn.hgetall(name='user001'))

redis列表操作

具体方法:

conn.lpush('list_name',val) # left_push操作,往指定名称的list左侧加入元素,没有该list的话则创建后加入元素

conn.rpush('list_name',val) # right_push操作,往指定名称的list右侧加入元素,没有该list的话则创建后加入元素

conn.lrange('list_name',start:,end:) # 返回指定列表中指定范围内的元素([start,end]闭区间)

conn.lset('list_name',index:,value:) # 设定指定列表中指定下标位置的值 index超出则报错

conn.lpop('list_name') # 弹出list左侧的元素并返回 left_pop()操作

conn.rpop('list_name') # 弹出list左侧的元素并返回 left_pop()操作

conn.llen('tasks')  # 获取列表长度

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None,
    decode_responses=True
)

print(conn.ping())

conn.lpush('list1',12)
print(conn.lrange('list1',0,-1)) #.lrange('task_name',start,end)可以指定访问范围,左右都是闭区间
#conn.lset('list1',0,123)
conn.lset('list1',0,678)
print(conn.lrange('list1',0,0))

print(conn.lpop('list1'))
print(conn.lrange('list1',0,-1))
length = conn.llen('tasks')
print(f"列表长度: {length}")

redis集合操作

具体方法:

conn.sadd(name:,*values:) #定义集合字段并加入元素/王已有的集合中添加元素

conn.smember(name:) # 获取集合中所有元素

conn.sismember('tags','python') #判断元素是否属于该集合

conn.srandmember('tags',2) # 随机获取number个集合元素(集合本身无序)

conn.spop('tags') # 弹出集合中的元素(随机)

conn.srem('tags','cpp') # remove操作,从集合中移除指定元素

运算:

conn.sinter('set1', 'set2') # set_inter交集运算

conn.sunion('set1', 'set2') # set_union交集运算

conn.sdiff('set1', 'set2') # set_difference交集运算

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None,
    decode_responses=True
)

conn.sadd('tags', 'python', 'java', 'cpp')  # set_add 向集合tags中添加元素

all_factors = conn.smembers('tags')
print(all_factors) #通过.smember('集合名称')获取集合内所有元素

if_exist = conn.sismember('tags','python') # is_member 判断元素是否属于该集合
print(if_exist)

random_factor = conn.srandmember('tags',2) # 随机获取number个集合元素
print(random_factor)

random_factor = conn.spop('tags') # 弹出集合中的元素,这一操作是随机的
print(random_factor)

conn.srem('tags','cpp') # remove操作,从集合中移除指定元素
print(conn.smembers('tags'))

# 集合运算
conn.sadd('set1', 'a', 'b', 'c')
conn.sadd('set2', 'b', 'c', 'd')

# 交集
intersection = conn.sinter('set1', 'set2') # set_inter交集运算
print("交集:", intersection)

# 并集
union = conn.sunion('set1', 'set2') # set_union交集运算
print("并集:", union)

# 差集 仅存在key_set中的元素 (set1-(set1与set2的交集))
difference = conn.sdiff('set1', 'set2') # set_difference交集运算
print("差集:", difference)

redis有序集合操作

具体方法

使用.zrange(name:,start:,end:,withscore=)针对特定name字段构造有序集合 可选desc降序

使用.zrevrange(name:,start:,end:,withscore=) 反转排序

conn.zscore(name:,key:) 获取有序集合中指定key的值

修改有序集合中的键值:

conn.zadd(name:,{key:,value:}) #更新指定name:集合中key对应的value ,没有则创建

conn.zincrby(name:,increment:,key:) # 给指定name:集合中key添加增量incremen

获取排名信息:
conn.zrank(name:,key:) #获取name:集合中key的相对排名(从0开始计算)

conn.zrevrank(name:,key:) #获取name:集合中key的反转相对排名(从0开始计算)

补充:

conn.zrangebyscore(name:,start:,end:,withscore:) #按照分数范围获取/构造有序集合

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None,
    decode_responses=True
)

# 添加带分数的元素
conn.zadd('leaderboard', {
    'player1': 1000,
    'player2': 1500,
    'player3': 800,
    'player4': 2000
}) #指定集合名称,通过mapping参数以dict方式传入元素集合

#Z 代表的是 Sorted Set(有序集合)

asc_sorted = conn.zrange('leaderboard',0,-1,withscores=True) #选定方位,根据values进行排序
print(asc_sorted)
#[('player3', 800.0), ('player1', 1000.0), ('player2', 1500.0), ('player4', 2000.0)]
decs_sorted = conn.zrange('leaderboard',0,-1,withscores=True,desc=True) #选定方位,根据values进行排序
#添加降序参数decs=True
print(decs_sorted)
#[('player4', 2000.0), ('player2', 1500.0), ('player1', 1000.0), ('player3', 800.0)]
#或者使用.zrevrange() 反转排序
decs_sorted = conn.zrevrange('leaderboard',0,-1,withscores=True)
print(decs_sorted)
#[('player4', 2000.0), ('player2', 1500.0), ('player1', 1000.0), ('player3', 800.0)]
#获取指定key对应的value
# 获取元素分数
score = conn.zscore('leaderboard', 'player2')
print(f"player2的分数: {score}")
#player2的分数: 1500.0
print(conn.zscore('leaderboard','player3'))
#800
#修改value 两种方式 .zadd()直接覆盖或者.zincrby()添加增量
conn.zadd('leaderboard',{'newplayer':2500})
conn.zadd('leaderboard',{'player2':2500})
print(conn.zrange('leaderboard',0,-1,withscores=True))
#[('player3', 800.0), ('player1', 1000.0), ('player4', 2000.0), ('newplayer', 2500.0), ('player2', 2500.0)]
conn.zincrby('leaderboard',500,'player2')
print(conn.zrange('leaderboard',0,-1,withscores=True))
#[('player3', 800.0), ('player1', 1000.0), ('player4', 2000.0), ('newplayer', 2500.0), ('player2', 3000.0)]

# 获取排名
rank = conn.zrank('leaderboard', 'player3')  # 从0开始的排名
print(f"player3的排名: {rank + 1}")  # 转换为从1开始的排名
rank = conn.zrevrank('leaderboard', 'player3')  # 从0开始的排名 反转
print(f"player3的排名: {rank + 1}")  # 转换为从1开始的排名
# player3的排名: 1
# player3的排名: 5

# 按分数范围获取
high_scores = conn.zrangebyscore('leaderboard', 1000, 5000, withscores=True) #附加排序
print("高分玩家:", high_scores)
#高分玩家: [('player1', 1000.0), ('player4', 2000.0), ('newplayer', 2500.0), ('player2', 3000.0)]

redis keys操作和过期时间

具体方法:

conn.exists(key:) #查询key:是否存在

conn.expire(key:,last_time) #给key:设置持续时间last_time ,时间结束则过期

conn.ttl(key:) #获取对应key:的剩余持续时间

conn.persist(key:) #移除过期时间 将key:变为永续

redis相似匹配/查找:

redis中使用*号来进行相似匹配(类似MySQL中的%)

conn.key('*') # 返回所有的key

conn.key('session:*') #返回前缀为session:的keys

conn.delete(key:) #删除对应键

import time

import redis

conn = redis.Redis(
    host='localhost',
    port=6379,
    db=0,
    password=None,
    decode_responses=True
)

conn.set('test_key','test_val')
if_exist = conn.exists('test_key')
print(if_exist)
# 1
conn.expire('test_key',3)#设置过期时间 3s
print(conn.get('test_key'))
#test_val
time.sleep(1)
ttl = conn.ttl('test_key') #获取剩余存活时间
print(f"剩余时间{ttl}")
#剩余时间2
conn.persist('test_key') #移除过期,设置为永续

# 查找匹配模式的键
all_keys = conn.keys('*') #此处使用*表示匹配任意
print("所有键:", all_keys)
#所有键: ['session:123', 'session:456', 'leaderboard', 'test_key']
conn.set('session:123',123)
conn.set('session:456',456)
session_keys = conn.keys('session:*') #模糊匹配 只要求前缀是session:的keys
print("会话键:", session_keys)
#会话键: ['session:123', 'session:456']
# 删除键
conn.delete('session:123')
print("删除后是否存在:", conn.exists('session:123'))
# 删除后是否存在: 0
conn.delete('session:456')
print("删除后是否存在:", conn.exists('session:456'))
print(conn.keys('*'))
# 删除后是否存在: 0
# ['leaderboard', 'test_key']

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值