Redis入门

5 篇文章 0 订阅

一、安装

  1. Redis
  2. Redis Desktop Manager




二、启动Redis服务器

redis-server

在这里插入图片描述




三、启动Redis客户端

redis-cli
  1. 检测 redis 服务是否启动
127.0.0.1:6379> ping
PONG
  1. 设置hello的值为world
127.0.0.1:6379> set hello world
OK
  1. 取出hello的值
127.0.0.1:6379> get hello
"world"
  1. 删除hello的值
127.0.0.1:6379> del hello
(integer) 1
127.0.0.1:6379> get hello
(nil)

(integer) 1为成功删除的数量,(nil)为空,在Python中则为None




四、Redis数据结构

结构类型存储的值功能
STRING字符串、整数、浮点数字符串操作、数值自增自减
LIST列表,每个节点为字符串两端推入或弹出数据、根据偏移量作修剪、读多个元素、查值或删值
SET集合添加获取删除单个元素、检查元素是否存在、交并差集、随机取元素
HASH键值对散列表添加获取删除单个键值对、获取所有键值对
ZSET有序集合添加获取删除单个元素、根据分值范围获取元素




五、Redis字符串STRING

1. 加减命令

命令作用
incr自增
decr自减
incrby加一个整数
decrby减一个整数
incrbyfloat加上一个浮点数

以下为redis-cli命令中的示例代码

127.0.0.1:6379> get number
(nil)
127.0.0.1:6379> incr number
(integer) 1
127.0.0.1:6379> incrby number 15
(integer) 16
127.0.0.1:6379> decrby number 5
(integer) 11
127.0.0.1:6379> get number
"11"
127.0.0.1:6379> set number '13'
OK
127.0.0.1:6379> incr number
(integer) 14
127.0.0.1:6379> incrbyfloat number 0.1
"14.1"
127.0.0.1:6379> incr number
(error) ERR value is not an integer or out of range

以下为Python示例代码

>>> import redis
>>> conn = redis.Redis()
>>> conn.get('number') # 一开始无值,自然没结果
>>> conn.incr('number') # 从0开始自增
1
>>> conn.incr('number', 15) # 加15
16
>>> conn.decr('number', 5) # 减5
11
>>> conn.get('number') # 获取
b'11'
>>> conn.set('number', '13') # 设置
True
>>> conn.incr('number') # 自增
14
>>> conn.incrbyfloat('number', 0.1)
14.1
>>> conn.incr('number')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  redis.exceptions.ResponseError: value is not an integer or out of range

变为浮点数后则不可再使用incr命令




2. 增改命令

命令作用
append追加
getrange获取子串
setrange修改部分
getbit将字符串看作二进制位串,返回对应二进制位的值
setbit将字符串看作二进制位串,设置对应二进制位的值
bitcount统计二进制位串值为1的数量,可给定范围
bitop对N个二进制位串执行并、或、异或、非操作
>>> import redis
>>> conn = redis.Redis()
>>> conn.append('str', 'hello ') # 插入不存在的键,返回当前长度
6
>>> conn.append('str', 'world!') # 返回当前长度
12
>>> conn.substr('str', 3, 7) # 2.6版本以上尽量用getrange
b'lo wo'
>>> conn.getrange('str', 3, 7) # 获取下标为3到7的值
b'lo Wo'
>>> conn.setrange('str', 0, 'H') # 将下标为0的值替换为H
12
>>> conn.setrange('str', 6, 'W') # 将下标为6的值替换为W
12
>>> conn.get('str')
b'Hello World!'
>>> conn.setrange('str', 11, ', how are you?') # setrange除了替换还可增加
25
>>> conn.get('str')
b'Hello World, how are you?'
>>> conn.setbit('str2', 2, 1)
0
>>> conn.setbit('str2', 7, 1)
0
>>> conn.get('str2')
b'!'

str2下标为2和下标为7的二进制位设为1,那么str2为00100001,通过ASCII编码转换得知!的10进制ASCII码为33,转换为二进制则对应00100001(2的5次方+2的零次方=33)




六、Redis列表LIST

1. 常用命令

命令作用
rpush右插
lpush左插
rpop右弹出
lpop左弹出
lindex获取单个元素
lrange获取范围元素
ltrim修剪(保留)
llen元素数量
lset设置
>>> import redis
>>> conn = redis.Redis()
>>> conn.rpush('l', 'last') # 右插
1
>>> conn.lpush('l', 'first') # 左插
2
>>> conn.rpush('l', 'new last') # 右插
3
>>> conn.lrange('l', 0, -1) # 遍历
[b'first', b'last', b'new last']

>>> conn.lpop('l') # 左弹出
b'first'
>>> conn.lpop('l')
b'last'
>>> conn.lrange('l', 0, -1)
[b'new last']
>>> conn.rpush('l', 'a', 'b', 'c') # 右推入
4
>>> conn.lrange('l', 0, -1)
[b'new last', b'a', b'b', b'c']
>>> conn.ltrim('l', 2, -1) # 左修剪
True
>>> conn.lrange('l', 0, -1)
[b'b', b'c']
>>> conn.lindex('l', 1)
b'c'

2. 阻塞式命令

命令作用
blpop阻塞式左弹出
brpop阻塞式右弹出
rpoplpush从列表1右弹出元素后左插入到列表2,同时返回该元素
brpoplpush阻塞式从列表1右弹出元素后左插入到列表2,同时返回该元素
>>> conn.lrange('l', 0, -1)
[b'b', b'c']
>>> conn.rpush('l2', 'a')
1
>>> conn.brpoplpush('l2', 'l', 1) # 阻塞1秒
b'a'
>>> conn.lrange('l', 0, -1)
[b'a', b'b', b'c']
>>> conn.lrange('l2', 0, -1)
[]
>>> conn.brpoplpush('l2', 'l', 1)

列表l2已不包含任何元素,调用阻塞式命令brpoplpush可以观察到这段时间在等待可弹出元素出现(等了1秒)

>>> conn.brpoplpush('l', 'l2', 1)
b'c'
>>> conn.lrange('l', 0, -1)
[b'a', b'b']
>>> conn.lrange('l2', 0, -1)
[b'c']
>>> conn.blpop(['l', 'l2'], 1) # 对两列表按顺序左弹出
(b'l', b'a') # 左弹出了列表l的元素
>>> conn.blpop(['l', 'l2'], 1)
(b'l', b'b') # 左弹出了列表l的元素
>>> conn.blpop(['l', 'l2'], 1)
(b'l2', b'c') # 左弹出了列表l2的元素
>>> conn.blpop(['l', 'l2'], 1)

把列表l最右元素弹到列表l2左端
对两列表按顺序左弹出一个元素,直到没元素为止

阻塞式命令常用于消息传递(messaging)和任务队列(task quene)




七、Redis集合SET

特点:无序、不能重复添加
对应Python中的集合set

1. 常用命令

命令作用
sadd添加
srem删除
sismember是否存在
scard元素数量
smembers所有元素
srandmember随机N个元素,正数不重复,负数可重复
spop随机弹出
smove移动集合1某元素到集合2
  1. 添加元素sadd和遍历所有元素smembers
127.0.0.1:6379> sadd day Monday
(integer) 1
127.0.0.1:6379> sadd day Tuesday
(integer) 1
127.0.0.1:6379> sadd day Wednesday
(integer) 1
127.0.0.1:6379> sadd day Monday
(integer) 0
127.0.0.1:6379> smembers day
1) "Wednesday"
2) "Monday"
3) "Tuesday"

可以观察到结果是无序的,并且不能重复添加
在Python中对应的数据结构为集合set

  1. 元素是否存在sismember
127.0.0.1:6379> sismember day Friday
(integer) 0
127.0.0.1:6379> sismember day Monday
(integer) 1
  1. 删除元素srem
127.0.0.1:6379> srem day Monday
(integer) 1
127.0.0.1:6379> smembers day
1) "Wednesday"
2) "Tuesday"

可以用Redis Desktop Manager查看
在这里插入图片描述

以下为Python示例代码

>>> import redis
>>> conn = redis.Redis()
>>> conn.sadd('day', 'Monday', 'Tuesday', 'Wednesday')
1
>>> conn.srem('day', 'Wednesday', 'Thursday') # 移除成功返回1
1
>>> conn.srem('day', 'Wednesday', 'Thursday') # 移除失败返回0
0
>>> conn.scard('day') # 元素数量
2
>>> conn.smembers('day') # 所有元素
{b'Tuesday', b'Monday'}
>>> conn.smove('day', 'day2', 'Monday') # 将day的Monday移动到day2
True
>>> conn.smove('day', 'day2', 'Wednesday')
False
>>> conn.smembers('day2')
{b'Monday'}

2. 组合和关联命令

命令作用
sdiff差集
sdiffstore差集(多集合)
sinter交集
sinterstore交集(多集合)
sunion并集
sunionstore并集(多集合)
>>> conn.sadd('s1', 'a', 'b', 'c', 'd') # 集合s1添加元素
4
>>> conn.sadd('s2', 'c', 'd', 'e', 'f') # 集合s2添加元素
4
>>> conn.sdiff('s1', 's2') # 集合s1减集合s2
{b'b', b'a'} # a和b
>>> conn.sinter('s1', 's2') # 集合s1、s2作交集
{b'd', b'c'} # c和d
>>> conn.sunion('s1', 's2') # 集合s1、s2作并集
{b'a', b'f', b'e', b'd', b'c', b'b'} # abcdef




八、Redis散列HASH

1. 常用命令

命令作用
hset添加
hget获取一个
hgetall遍历
hdel删除
hmget获取多个值
hmset添加多个值
hlen键值对数量
  1. 添加键值对hset
127.0.0.1:6379> hset day-hash Monday 1
(integer) 1
127.0.0.1:6379> hset day-hash Tuesday 2
(integer) 1
127.0.0.1:6379> hset day-hash Wednesday 3
(integer) 1
127.0.0.1:6379> hset day-hash Monday 1
(integer) 0

day-hash为散列名,后面跟key value

  1. 遍历
127.0.0.1:6379> hgetall day-hash
1) "Monday"
2) "1"
3) "Tuesday"
4) "2"
5) "Wednesday"
6) "3"

在Python中对应的数据结构为字典dict

  1. 获取单个元素hget
127.0.0.1:6379> hget day-hash Monday
"1"
  1. 删除hdel
127.0.0.1:6379> hdel day-hash Monday
(integer) 1
127.0.0.1:6379> hdel day-hash Monday
(integer) 0
127.0.0.1:6379> hgetall day-hash
1) "Tuesday"
2) "2"
3) "Wednesday"
4) "3"

以下为Python示例代码

>>> import redis
>>> conn = redis.Redis()
>>> conn.hmset('day-hash', {'Monday':1, 'Tuesday':2, 'Wednesday':3}) # 设置键值对
True
>>> conn.hmget('day-hash', ['Monday', 'Tuesday']) # 获取多个键值对
[b'1', b'2']
>>> conn.hlen('day-hash') # 键值对数量
3
>>> conn.hdel('day-hash', 'Monday', 'Wednesday') # 删除多个键值对
2
>>> conn.hgetall('day-hash') # 遍历
{b'Tuesday': b'2'}

2. 批量命令

命令作用
hexists是否存在
hkeys所有键
hvals所有值
hgetall所有键值对
hincrby加个整数
hincrbyfloat加个浮点数

hkeys用于避免使用hgetall一次取出多个大体积的值造成的服务器阻塞。可先用hkeys取出所有键,再使用hget一个个取出值

>>> conn.hmset('hash-key', {'short':'hello', 'long':1000*'1'})
True
>>> conn.hgetall('hash-key') # 不推崇这种做法
# 结果忽略
>>> conn.hkeys('hash-key') # 推崇逐个取出键值的做法
[b'long', b'short']
>>> conn.hexists('hash-key', 'num')
False
>>> conn.hincrby('hash-key', 'num') # 不存在的键自增将会新建一个
1
>>> conn.hexists('hash-key', 'num')
True




九、Redis有序集合ZSET

有序集合zset类似散列hash,用于存储键值对
有序集合的键称为成员member,值称为分值score

1. 常用命令

命令作用
zadd添加
zrange按序遍历
zrangebyscore给定范围遍历
zrem删除
zcrad元素数量
zincrby加上一个数
zcount介于min和max间的元素数量
zrank在有序集合中的排名
zscore某元素的分值
  1. 添加成员分值zadd
127.0.0.1:6379> zadd grade 80 chinese
(integer) 1
127.0.0.1:6379> zadd grade 100 math
(integer) 1
127.0.0.1:6379> zadd grade 90 english
(integer) 1

注意!添加时的书写不同于键值对,是先分值再成员

  1. 升序遍历zrange
127.0.0.1:6379> zrange grade 0 -1 withscores
1) "chinese"
2) "80"
3) "english"
4) "90"
5) "math"
6) "100"

在Python中对应的数据结构为字典dict,并且分值会转换成浮点数

  1. 根据分值获取元素zrangebyscore
127.0.0.1:6379> zrangebyscore grade 0 90 withscores
1) "chinese"
2) "80"
3) "english"
4) "90"
  1. 删除zrem
127.0.0.1:6379> zrem grade english
(integer) 1
127.0.0.1:6379> zrem grade english
(integer) 0
127.0.0.1:6379> zrange grade 0 -1 withscores
1) "chinese"
2) "80"
3) "math"
4) "100"

以下为Python示例代码

>>> import redis
>>> conn = redis.Redis()
>>> conn.zadd('zset-key', {'a':3, 'b':2, 'c':1}) # 添加
3
>>> conn.zcard('zset-key') # 元素数量
3
>>> conn.zincrby('zset-key', 3, 'c') # 给键c的值加3
4.0
>>> conn.zscore('zset-key', 'b') # 获取键b的值
2.0
>>> conn.zrank('zset-key', 'c') # 键c的值的排序(从0开始从小到大)
2
>>> conn.zcount('zset-key', 0, 3) # 计算0-3范围内的值的数量
2
>>> conn.zrange('zset-key', 0, -1, withscores=True) # 从小到大遍历
[(b'b', 2.0), (b'a', 3.0), (b'c', 4.0)]
>>> conn.zrem('zset-key', 'b') # 删除键b
1
>>> conn.zrange('zset-key', 0, -1, withscores=True)
[(b'a', 3.0), (b'c', 4.0)]

2. 范围命令

命令作用
zrevrank从大到小排名
zrevrange给定排名范围,从大到小输出
zrangebyscore给定范围遍历
zrevrangebyscore给定范围遍历,从大到小输出
zremrangebyrank给定排名范围删除
zremrangebyscore给定范围删除
zinterstore交集
zunionstoore并集

以下为Python示例代码

>>> conn.zadd('zset-1', {'a':1, 'b':2, 'c':3})
3
>>> conn.zadd('zset-2', {'b':4, 'c':1, 'd':0})
3
>>> conn.zinterstore('zset-3', ['zset-1', 'zset-2']) # 取交集并调用聚合函数,默认为sum(),即将对应值加起来
2
>>> conn.zrange('zset-3', 0, -1, withscores=True)
[(b'c', 4.0), (b'b', 6.0)]
>>> conn.zunionstore('zset-4', ['zset-1', 'zset-2'], aggregate='min') # 取并集,聚合函数为min(),重复则取最小值
4
>>> conn.zrange('zset-4', 0, -1, withscores=True)
[(b'd', 0.0), (b'a', 1.0), (b'c', 1.0), (b'b', 2.0)]
>>> conn.sadd('set-1', 'a', 'd') # 新建集合set-1
2
>>> conn.zunionstore('zset-5', ['zset-1', 'zset-2', 'set-1']) # 此时set-1中的键值默认为1,默认聚合为sum()即加1
4
>>> conn.zrange('zset-5', 0, -1, withscores=True)
[(b'd', 1.0), (b'a', 2.0), (b'c', 4.0), (b'b', 6.0)]




十、Web应用

Web应用是通过HTTP协议对浏览器发来的请求进行相应的服务
Web服务器的响应步骤如下:

  1. 服务器对客户端发来的请求(request)进行解析
  2. 转发请求给预定义的处理器(handler)
  3. 处理器可能从数据库中取出数据
  4. 处理器根据取出的数据对模板(template)进行渲染(render)
  5. 处理器向客户端返回渲染后的内容作为对请求的响应(response)

登录网站时,网站会用cookie记录身份,常用签名(signed)cookie和令牌(token)cookie。令牌cookie有添加信息简单、体积小的优点,缺点是相对签名cookie来说,需要在服务器中存储更多信息。

使用令牌cookie存储用户登录信息,除此之外,还可以存储用户访问时长和已浏览商品等信息,便于未来进行学习推荐。




十一、发布与订阅

发布与订阅(又称pub/sub):订阅者(publisher)可订阅频道,发送者负责向频道发送二进制字符串消息。每当有消息发送到指定频道时,频道的所有订阅者都会收到消息。订阅者可以同时订阅多个频道,发送者可以在任何频道发消息。

在这里插入图片描述
缺点:

  1. 低版本Redis积压过多信息会使缓冲区体积过大,严重可导致系统崩溃
  2. 客户端执行订阅操作时断线将丢失这期间发送的信息

缺点1可通过新版本设置client-output-buffer-limit pubsub自动断开不符合配置的客户端解决

命令作用
subscribe订阅频道
unsubscribe退订频道
publish向频道发消息
psubscribe订阅匹配频道
punsubscribe退订匹配频道
import time
import redis
from threading import Thread

conn = redis.Redis()


def publisher(n):
    time.sleep(1)  # 发送者先休眠让订阅者有时间连服务器监听消息
    for i in range(n):
        conn.publish('channel', i)  # 发布信息
        time.sleep(1)


if __name__ == "__main__":
    Thread(target=publisher, args=(3,)).start()  # 创建发送者
    pubsub = conn.pubsub()  # 创建订阅者
    pubsub.subscribe(['channel'])  # 订阅频道
    count = 0
    for item in pubsub.listen():  # 监听订阅消息
        print(item)  # 接收到的消息
        count += 1
        if count == 4:
            pubsub.unsubscribe()
        if count == 5:
            break
{'type': 'subscribe', 'pattern': None, 'channel': b'channel', 'data': 1}
{'type': 'message', 'pattern': None, 'channel': b'channel', 'data': b'0'}
{'type': 'message', 'pattern': None, 'channel': b'channel', 'data': b'1'}
{'type': 'message', 'pattern': None, 'channel': b'channel', 'data': b'2'}
{'type': 'unsubscribe', 'pattern': None, 'channel': b'channel', 'data': 0}




十二、通用命令

  1. 排序sort
    可以将sort看成SQL语言中的order by
>>> conn.rpush('sort-input', 23, 15, 110, 7) # 列表右插
4
>>> conn.sort('sort-input') # 从小到大排
[b'7', b'15', b'23', b'110']
>>> conn.sort('sort-input', alpha=True) # 根据字母表排
[b'110', b'15', b'23', b'7']
>>> conn.hset('d-7', 'field', 5) # 散列
1
>>> conn.hset('d-15', 'field', 1)
1
>>> conn.hset('d-23', 'field', 9)
1
>>> conn.hset('d-110', 'field', 3)
1
>>> conn.sort('sort-input', by='d-*->field') # 列表元素赋予对应权重,按权重从小到大输出。d-7的field为5,则列表中的7权重为5
[b'15', b'110', b'7', b'23']
>>> conn.sort('sort-input', by='d-*->field', get='d-*->field')
[b'1', b'3', b'5', b'9'] # 获取外部数据并将其作为命令的返回值




十三、Redis事务

事务可以让一个客户端在不被其他客户端打断的情况下执行多个命令。被multi命令和exec命令包围的所有命令会逐个执行。当一个事务执行完毕后,Redis才会处理其他客户端的命令。

Redis事务在Python客户端上通过流水线(pipeline)实现。

不使用事务,并行自增

import time
import redis
from threading import Thread

conn = redis.Redis()


def notrans():
    print(conn.incr('notrans:'))  # 自增
    time.sleep(.1)  # 休眠
    conn.incr('notrans:', -1)  # 自减


if __name__ == "__main__":
    for i in range(3):
        Thread(target=notrans).start()
    time.sleep(.5)  # 等待让操作完成
1
2
3

可以看到, 因没使用事务,3个线程各个命令交错进行,计数器值持续增大(理想应一直为1)

使用事务,并行自增

import time
import redis
from threading import Thread

conn = redis.Redis()


def trans():
    pipeline = conn.pipeline()  # 创建事务型流水线对象
    pipeline.incr('trans:')
    time.sleep(.1)
    pipeline.incr('trans:', -1)
    print(pipeline.execute()[0])  # 执行被事务包裹的命令,并打印结果


if __name__ == "__main__":
    for i in range(3):
        Thread(target=trans).start()
    time.sleep(.5)  # 等待让操作完成
1
1
1

可以看到,尽管自增自减操作间有时间延迟,但使用事务,各个线程都可以在不被其他线程打断下执行各自队列里的命令。




十四、过期时间

使用Redis存储数据时,许多数据在某个时间点后就不再使用,除了可以用del命令显示删除无用数据,还可通过设置键的过期时间(expiration)自动被删除。

键过期命令只能为整个键设置过期时间,但无法直接为键里的单个元素设置过期时间。可通过存储时间戳的有序集合实现对单个元素的过期操作。

命令作用
persist移除键的过期时间
ttl查看距离过期还有多少秒
expire设置过期时间(秒)
expireat设置过期时间(Unix时间戳)
pttl查看距离过期还有多少毫秒
pexpire设置过期时间(毫秒)
pexpireat设置过期时间(Unix时间戳)
>>> import time
>>> conn.set('key', 'value')
True
>>> conn.get('key')
b'value'
>>> conn.expire('key', 2) # 为key设置过期时间2秒
True
>>> time.sleep(2) # 休眠2秒
>>> conn.get('key') # 获取key的值,发现为空
>>> conn.set('key', 'value2')
True
>>> conn.expire('key', 100); conn.ttl('key') # 设置过期时间同时输出距离过期时间的秒数
True
100




常用命令

所有键值:KEYS *

以x开头的所有键值:KEYS x*

键值有效时间:TTL 键名

查看版本(命令行外):redis-server --version

查看版本(命令内):INFO




TODO

Redis在实际应用开发中的常见作用包括:

  1. 缓存
    Redis提供字符串、列表、集合、散列等多种数据结构来缓存数据,可以用来缓存数据库查询结果、API响应等,提升应用性能。
  2. 消息队列
    Redis的列表结构可以实现消息队列,用作异步任务队列,削峰填谷等。
  3. 计数器/限速器
    Redis的字符串和哈希结构可以通过INCR命令实现计数器功能,从而实现限流、限速。
  4. 设置与获取
    Redis可以当作高速的键值存储,用于设置和获取应用配置、用户配置、元数据等。
  5. 会话存储
    Redis可以用于存储用户会话信息,如购物车、登录信息等。
  6. 分布式锁
    借助SETNX实现分布式锁,用于控制对共享资源的并发访问。
  7. 实时消息
    Pub/Sub可实现发布订阅消息,用于实时通知、消息推送等功能。
  8. 地理位置
    Redis Geo可用于地理位置查询,打车距离计算等。
  9. 流量分析
    RedisTimeSeries可存储时间序列数据,实现实时流量分析。
    综上所述,Redis在应用开发中是一个多面手,可以灵活运用于缓存、消息、计数器、会话等多种场景。

使用Redis作为缓存时,主要需要注意以下几个方面的问题:

  1. 缓存穿透
    查询不存在的数据时,由于缓存不命中,请求直达后端数据库,可能压垮数据库。
    解决方案是使用布隆过滤器或在Redis设置默认值进行占位。
  2. 缓存雪崩
    大量键同时失效,引发大量请求到数据库,造成数据库压力。
    解决方案是采用随机过期时间、Redis高可用以及限流降级。
  3. 缓存一致性
    缓存和数据库存在一致性问题,数据更新后缓存未及时失效。
    解决方案是采用失效策略、事件驱动更新或定期主动刷新。
  4. 热点缓存键
    部分缓存键访问频率很高,导致Redis内存不均衡。
    解决方案是采用分片或集群方式扩展。
  5. 内存限制
    Redis内存用量受限,可能引起写入失败和内存淘汰。
    解决方案是监控用量变化,扩容或限制缓存大小。
  6. 单点故障
    Redis未采用集群模式,存在单点故障风险。
    解决方案是搭建Redis高可用集群。
    因此在使用Redis缓存时,需要全面考虑这些问题和解决方案。

在Redis中缓存数据时,缓存键(Key)的命名需要注意以下几点:

  1. 直观:键名要能反映出存储的数据含义,一目了然。
  2. 规范:对键名采用一定的规范,如user🆔001表示用户id为001的用户数据。
  3. 唯一:键名要唯一,不要重复,以免发生冲突覆盖。
  4. 散列:要散列化存储,不要使用递增键名,可以通过hash、前缀、时间戳等拼接键名。
  5. 简短:键名不要过长,通常控制在10-20个字符,可以节省内存。
  6. 不包含特殊字符:不要在键名中使用空格、换行符等特殊字符。
  7. 区分中间层:可以在键名中体现缓存数据从哪些中间层流转而来。
  8. 动态生成:也可以考虑在程序中动态生成键名,而不是硬编码。
  9. 命名空间:可以为不同业务区分不同的键名命名空间,防止键名冲突。
  10. 过期时间:可以将过期时间信息包含在键名中,便于后续处理。
    总之,Redis键名的命名要富有意义、规范且唯一,是一个需要注意的细节。

使用Python编写一个Redis缓存装饰器,给Flask接口添加缓存功能:

import redis
from functools import wraps
from flask import current_app, request

# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)

def cache(expire=300):
    def wrapper(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 生成缓存key
            key = "cache_{}_{}".format(request.path, request.args) 
            # 获取缓存数据
            cache_data = r.get(key)  
            if cache_data:
                return cache_data
            # 缓存不存在,调用函数获取数据
            response = f(*args, **kwargs)           
            # 设置缓存
            r.set(key, response, ex=expire)  
            return response
        return decorated_function
    return wrapper

@app.route('/data')
@cache(expire=3600)
def get_data():
    return {'data': 'hello'} 




推荐文章

  1. Redis 分布式锁没这么简单,网上大多数都有 bug
  2. Redis 为什么快?
  3. Redis最佳实践:7个维度+43条使用规范
  4. 工作中用Redis最多的10种场景
  5. python中布隆过滤器用法详解:解决缓存穿透的问题,它说存在就可能不存在,它说不存在就一定不存在,不过一般会改用存空值来解决问题
  6. 我使用缓存,踩过的7个坑




参考文献

  1. Redis 教程 | 菜鸟教程
  2. Redis实战
  3. Redis命令参考
  4. Python Redis文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XerCis

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值