Redis 基础、缓存、String/Hash

目录

参考资料:

Redis介绍:

[1. 节省内存,防止数据堆积](#1. 节省内存,防止数据堆积)

[2. 保证数据时效性](#2. 保证数据时效性)

[3. 模拟会话(Session)行为](#3. 模拟会话(Session)行为)

[4. 无需手动维护清理任务](#4. 无需手动维护清理任务)

[5. 典型应用场景](#5. 典型应用场景)

[Python 操作 Redis](#Python 操作 Redis)

安装依赖:

string和hash操作

[FastAPI + Redis 简单实战](#FastAPI + Redis 简单实战)

[考察:用 Redis 缓存 API 结果,提升性能。](#考察:用 Redis 缓存 API 结果,提升性能。)

启动:

测试:

实战项目

核心逻辑(高频框架):

测试


参考资料:

redis的基本使用Redis的原理与使用

Redis介绍:

与MySQL数据库不同,MySQL数据库有表、有字段、有记录,Redis没有这些东西,就是一个名称对应一个值,并且数据以存储在内存中使用为主。

Redis自身并不是为了数据持久化而生的,主要是在内存中保存数据,加速数据访问的。

Redis在AI Infra 里作用:

  1. 缓存大模型对话历史(用户和 AI 聊的内容存在 Redis,避免重复发送给模型)
  2. 缓存 Embedding 向量(文档转成的向量存在 Redis,下次查询直接用,省 GPU 钱)
  3. 缓存热点数据(比如频繁访问的模型配置、用户信息)
  4. 接口限流(防止模型被恶意调用刷爆)

Redis 中设置过期时间(TTL) 的核心作用是自动管理数据生命周期,具体到 AI 服务场景有以下关键用途:

1. 节省内存,防止数据堆积

对话历史、临时缓存等数据如果不删除,会无限占用 Redis 内存。设置过期时间(如 1 小时)后,数据到期自动释放,避免 OOM(内存溢出)。

2. 保证数据时效性

AI 对话通常只需保留最近一段时间(如 1 小时)的上下文。过期机制自动淘汰陈旧数据,防止模型读到过时的用户问题或已失效的配置。

3. 模拟会话(Session)行为

就像 Web 应用的 Session 过期一样,用户对话无活动一段时间后,Redis 自动清除该会话的历史记录,下次用户访问会重新开始。

4. 无需手动维护清理任务

不需要写定时任务或后台脚本来扫描删除过期键,Redis 内部惰性删除 + 定期删除自动完成,简化代码逻辑。

5. 典型应用场景

  • 限流计数器expire(rate_limit_key, 60) 让计数器每分钟自动重置。

  • 临时授权码:验证码 5 分钟失效。

  • 缓存 Embedding 向量:模型更新后,旧向量自动过期。

Python 操作 Redis

安装依赖:

python 复制代码
pip install redis

string和hash操作

python 复制代码
import redis
# 连接(decode_responses=True 让返回值是字符串,不是字节)
r=redis.Redis(host='localhost',port=6379,db=0,decode_responses=True)

# string操作
# 缓存模型配置
r.set("model:default","qwen-7b")
print(r.get("model:default")) 

# 统计接口调用次数
r.set("api:call_count",0)
r.incr("api:call_count")#自增1
print(r.get("api:call_count"))

# hash操作
user_id="user_001"
conversation_key=f"conversation:{user_id}"
r.hset(conversation_key,mapping={
    "user_question": "Redis 在 AI 服务里有什么用?",
    "ai_answer": "缓存对话历史、Embedding 向量、接口限流...",
    "timestamp": "2024-07-22 10:00:00"
})

#取对话
print(r.hgetall(conversation_key))

# 设置过期时间
r.expire(conversation_key,3600)

FastAPI + Redis 简单 实战

考察:用 Redis 缓存 API 结果,提升性能。

python 复制代码
from fastapi import FastAPI
import redis
import time
import hashlib

app=FastAPI()
r=redis.Redis(host='localhost',port=6379,db=0,decode_responses=True)

# 模拟大模型生成回答的耗时操作
def generate_answer(question:str)->str:
        time.sleep(2)
        return f"AI 回答:{question}的答案。。。"

# 带ai缓存的ai回答接口
@app.get("/ai/ask/{question}")
def ask_ai(question:str):
        # 生成缓存key(问题的MD5作为唯一标识)
        cache_key=f"ai_answer:{hashlib.md5(question.encode()).hexdigest()}"

        # 先查缓存
        cache_answer=r.get(cache_key)
        if cache_answer:
                return{
                        "answer": cache_answer,
                        "source": "redis_cache",  # 来源:缓存
                        "time": "0001s"
                }
        # 缓存没命中,调用大模型
        start_time=time.time()
        answer=generate_answer(question)

        end_time=time.time()

        # 把 AI 生成的答案,先存到 Redis 里,并且只保存 10 分钟。10 分钟后,自动删除。
        r.set(cache_key,answer,ex=600)

        return{
                "answer": answer,
                "source": "model_generated",  # 来源:大模型
                "time": f"{end_time - start_time:.3f}s"
        }

启动:

用于启动 Uvicorn 服务器的命令,通常用来运行 FastAPI 或任何 ASGI 应用程序

python 复制代码
uvicorn curd2:app --reload
部分 含义
uvicorn ASGI 服务器(支持异步 Python Web 框架,如 FastAPI、Starlette)
curd2:app 告诉 Uvicorn 去curd2.py 文件中寻找名为 app 的 ASGI 应用对象(通常是 FastAPI() 实例)
--reload 开启自动重载模式:代码文件修改后,服务器会自动重启,无需手动停止再启动(开发时非常方便)仅在开发环境使用,生产环境不会加此参数(因为会浪费资源且不够稳定)

测试:

第一次访问:http:127.0.0.1:8000/ai/ask/提示信息

立即再次访问同一问题

实战项目

核心逻辑(高频框架):

  1. 客户端请求用户信息

  2. 先查 Redis 缓存

  3. 有数据 → 直接返回(极速)

  4. 无数据 → 查询 MySQL

  5. 查到数据 → 写入 Redis 缓存,设置过期时间

  6. 无数据 → 返回 404

python 复制代码
from fastapi import FastAPI,HTTPException
from sqlalchemy import create_engine,Column,Integer,String,DateTime
from sqlalchemy.orm import declarative_base,sessionmaker
from datetime import datetime
import redis

mysql_url="mysql+pymysql://root:123456@localhost:3306/ai_infra"
# pool_pre_ping=True是否是后连接,扔掉死连接,创建活连接
engine=create_engine(mysql_url,pool_pre_ping=True)
# 创建会话:关闭自动提交, 不自动把临时数据同步到数据库,告诉会话要绑定到哪个数据库
SessionLocal=sessionmaker(autocommit=False,autoflush=False,bind=engine)
Base=declarative_base()

# redis配置
redis_client=redis.Redis(
    host="localhost",
    port=6379,
    db=0,
    decode_response=True
)
# FastApi实例
app=FastAPI(title="缓存未命中回写")

# 数据库模型
class User(Base):
    __tablename__="user" #给 Python 类绑定 MySQL 表名
    id=Column(Integer,primary_key=True,index=True)
    username=Column(String(50),unique=True,nullable=False)
    age=Column(Integer)
    create_time=Column(DateTime,default=datetime.now)
# 不存在则自动建
Base.metadata.create.all(bind=engine)
# 数据库会话工具
def get_db():
    db=SessionLocal()
    try:
        yield db
    finally:
        db.close()
# 缓存+数据库
@app.get("/api/user/{username}")
def get_user_info(username:str):
    cache_key=f"user:info:{username}"
    # 1.查询redis缓存
    cache_data=redis_client.hgetall(cache_key)
    if cache_data:
        return{
            "code": 200,
            "msg": "缓存命中",
            "data": cache_data,
            "source": "Redis缓存"
        }
    
    # 2.缓存未命中,查询mysql
    db=next(get_db())
    user=db.query(User).filter(User.username==username).first()
    if not user:
        raise HTTPException(status_code=404,detail="用户不存在")
    
    # 3.数据库数据写入Redis,设置缓存过期时间10分钟
    user_dict={
        "id":user.id,
        "username":user.username,
        "age":user.age
    }
    redis_client.hset(cache_key,mapping=user_dict)
    redis_client.exprie(cache_key,600)

    return {
        "code":200,
        "msg":"数据库查询成功",
        "data":user_dict,
        "source":"mysql数据库"
    }

# 新增用户的接口
@app.post("/api/user/add")
def add_user(username:str,age:int,db=next(get_db())):
    # 判断是否存在用户
    exist_user=db.query(User).filter(User.username==username).first()
    if exist_user:
        raise HTTPException(status_code=400,detail="该用户名已经存在")
    
    new_user=User(username=username,age=age)
    db.add(new_user)
    db.commit()
    return {
        "code":200,
        "msg":"创建成功",
        "username":"username"
    }

测试

0.本地必须启动:MySQL 服务(根据引擎中的数据库信息创建数据库)、Redis 服务

终端启动服务,启动成功后

打开自动接口文档:http://127.0.0.1.800/docs

1.先调用/api/user/add 添加用户"偏偏意气用事"

2.再次添加,检查"判断是否存在"

3.调用/api/user/add第一次查用户:来源 = MySQL

4.第二次重复查询:来源 = Redis 缓存

5.查询用户名"不想睡觉",无数据 → 返回 404

相关推荐
Devin~Y2 小时前
大厂Java面试实战:Spring Boot + Redis + Kafka + Kubernetes + RAG 的三轮追问(附答案解析)
java·spring boot·redis·spring cloud·kafka·kubernetes·resilience4j
字节高级特工2 小时前
迈入Redis:持久化
数据库·redis·缓存
进击的荆棘2 小时前
C++起始之路——用哈希表封装myunordered_set和myunordered_map
开发语言·c++·stl·哈希算法·散列表·unordered_map·unordered_set
人道领域4 小时前
【Redis实战篇】初步基于Redis实现的分布式锁---基于黑马点评
java·数据库·redis·分布式·缓存
Lyyaoo.12 小时前
Redis基础
数据库·redis·缓存
yuweiade13 小时前
Spring Boot 整合 Redis 步骤详解
spring boot·redis·bootstrap
JH307315 小时前
RedLock-红锁
java·redis
一嘴一个橘子16 小时前
redis 启动
redis
if else16 小时前
Redis 哨兵集群部署方案
数据库·redis