Redis¶
简介¶
Redis 是一个使用 ANSI C 编写的、开源的、基于内存的键值存储系统。它支持网络连接,并提供了多种语言的 API。虽然常被用作缓存,但其能力远不止于此。它可以作为:
-
数据库:持久化存储结构化数据。
-
缓存:为后端数据库提供毫秒级响应的读取层。
-
消息中间件:通过发布/订阅模式实现应用解耦。
核心特点:
-
极致性能:数据存储在内存中,读写速度极快,官方基准测试可达10万+ QPS。
-
丰富数据结构:原生支持字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等,还支持位图(Bitmap)、HyperLogLog、地理空间(Geo)等高级数据类型。
-
持久化能力:提供 RDB(快照)和 AOF(追加日志)两种持久化机制,确保数据安全。
-
高可用与可扩展:通过主从复制、哨兵(Sentinel)模式和原生集群(Cluster)模式,轻松构建高可用、可水平扩展的分布式系统。
-
原子性操作:所有单个命令都是原子性的,并支持事务(MULTI/EXEC)和 Lua 脚本,以保证复杂操作的原子性
Redis 应用领域¶
Web后端:会话存储、页面缓存、API响应缓存
实时分析:排行榜、计数器、实时仪表盘
消息队列:任务队列、事件驱动架构
AI/ML:RAG(检索增强生成)的向量数据库、特征存储
游戏:玩家状态、实时排行榜、社交关系
物联网:设备状态、实时数据流处理
金融:交易限流、欺诈检测、实时风控
Redis在RAG中的使用¶
什么是检索增强生成(RAG)?
大型语言模型 (LLM) 生成类似人类的文本,但受其训练数据的限制。RAG 通过将其与存储在 Redis 向量数据库中的外部领域特定数据集成来增强 LLM。
RAG 包括三个主要步骤
- 检索:使用向量搜索和基于用户查询的过滤器从 Redis 中获取相关信息。
- 增强:为 LLM 创建提示,包括用户查询、相关上下文和附加指令。
- 生成:将 LLM 生成的响应返回给用户。
RAG 使 LLM 能够使用实时信息,提高生成内容的准确性和相关性。Redis 因其速度、多功能性和易用性而成为 RAG 的理想选择。
Redis 在 RAG 中的作用:
Redis 为管理实时数据提供了一个强大的平台。它支持向量的存储和检索,这对于处理大规模、非结构化数据和执行相似性搜索至关重要。Redis 使其适用于 RAG 的主要特性和组件包括
- 向量数据库:存储和索引语义表示非结构化数据的向量嵌入。
- 语义缓存:在 RAG 流水线中缓存常见问题 (FAQ)。使用向量搜索,Redis 检索先前回答的类似问题,降低 LLM 推理成本和延迟。
- LLM 会话管理器:存储 LLM 和用户之间的对话历史记录。Redis 获取聊天历史记录中最近且相关的部分以提供上下文,从而提高响应的质量和准确性。
- 高性能和可扩展性:Redis 以其低延迟和高吞吐量而闻名,是需要快速数据检索和生成的 RAG 系统和 AI 代理的理想选择。
使用 Redis 构建 RAG 应用:
要使用 Redis 构建 RAG 应用,请遵循以下一般步骤
-
设置 Redis:首先设置一个 Redis 实例并将其配置为处理向量数据。
-
使用框架:
-
Redis 向量库 (RedisVL):RedisVL 通过高效管理向量和元数据来增强生成式 AI 应用的开发。它允许存储向量嵌入并促进快速相似性搜索,这对于在 RAG 中检索相关信息至关重要。
- 流行的 AI 框架:Redis 与各种 AI 框架和工具无缝集成。例如,将 Redis 与用于构建语言模型的库 LangChain 或 LlamaIndex 结合使用,使开发人员能够创建复杂的 RAG 流水线。这些集成支持高效的数据管理和构建实时 LLM 链。
- Spring AI 和 Redis:使用带有 Redis 的 Spring AI 简化了 RAG 应用的构建。Spring AI 提供了一种结构化的方法来将 AI 功能集成到应用中,而 Redis 处理数据管理,确保 RAG 流水线高效且可扩展。
-
嵌入并存储数据:使用合适的模型(例如 BERT、GPT)将数据转换为向量嵌入。将这些嵌入存储在 Redis 中,在那里可以基于向量搜索快速检索它们。
-
与生成模型集成:使用可以利用检索到的数据的生成式 AI 模型。该模型将使用存储在 Redis 中的向量来增强其生成过程,确保输出信息相关且最新。
-
查询和生成:实现查询逻辑,根据输入提示从 Redis 中检索相关向量。将这些向量输入生成模型以产生增强的输出。
使用 Redis 进行 RAG 的优势: * 效率:Redis 的内存数据存储确保检索操作以最小的延迟执行。 * 可扩展性:Redis 可以横向扩展,无缝处理不断增长的数据量和查询。 * 灵活性:Redis 支持各种数据结构并与 AI 框架集成。
总而言之,Redis 为实现 RAG 提供了一个强大且高效的平台。其向量管理功能、高性能以及与 AI 框架的无缝集成使其成为利用实时数据检索增强生成式 AI 应用的理想选择。
用Redis构建RAG应用代码¶
1.搭建并配置 Redis 环境
首先需要一个 Redis 实例,推荐用支持向量搜索的版本(比如 Redis 6.2+)。安装后,通过配置文件开启向量索引支持,确保能存储和检索向量嵌入。如果是云环境,也可以直接用 Redis Cloud,省去本地部署的麻烦。Redis Cloud官方网站
2.选择合适的开发框架
单独操作 Redis 可能有点繁琐,借助框架能事半功倍:
- RedisVL:Redis 官方的 Python 库,专门优化了向量和元数据管理,支持快速构建向量索引、执行相似性搜索,还集成了 CLI 工具,调试起来很方便。
- 主流 AI 框架:Redis 能和 LangChain、LlamaIndex 等无缝集成。比如用 LangChain 时,只需几行代码就能把 Redis 设为向量存储,再搭配 LLMs(如 GPT-3.5)构建完整的 RAG 管道,快速实现 “检索→增强→生成” 的全流程。
3.嵌入数据并存储到 Redis
把需要用到的外部数据(如文档、知识库)转换成向量嵌入:
- 先用嵌入模型(如 Sentence-BERT)把文本转换成向量(比如每个文本转成 768 维向量);
- 用 RedisVL 或 LangChain 的 API,将向量和对应的元数据(如文本内容、来源)一起存储到 Redis 中,并创建向量索引(指定距离度量方式,如余弦相似度)。
4.集成生成式模型
选择一个合适的 LLM(如 GPT-4、Llama 2 等),通过 API 或本地部署的方式集成到系统中。关键是要让 LLM 能接收 “用户查询 + 检索到的上下文” 作为输入,比如构造这样的提示:“基于以下上下文回答用户问题:{检索到的文档内容}\n 用户问题:{user_query}”。
5.实现查询与生成逻辑
当用户输入查询时,系统会:
- 用同样的嵌入模型把查询转换成向量;
- 调用 Redis 的向量搜索,根据相似度从索引中找到 Top N 相关文档;
- 把这些文档内容和用户查询整合成提示,传给 LLM;
- 接收 LLM 的回复,返回给用户。
示例代码:
这里直接用 Redis Cloud云环境,不用本地部署。但注意连接方式,可以参考带你入门免费的Redis Cloud。还有几个注意的点:
* redisvl 在 load() 时,通常需要的是:字符串、数字、bytes或者它能自动处理的向量格式,有时候embedding返回的是 Python 的 list,就会报错。可以把向量转成字节数组,embedding = np.array(vectorizer.embed(doc), dtype=np.float32).tobytes()
* 有时候连接的方式/端口/服务端协议不匹配也会报错,比如你设置了ssl=True,而Redis Cloud 需要 TLS,你用了错误的连接方式。
关于第二点,我在应用时踩过坑,你只需要检查
1)确认这个端口是不是 TLS 端口
Redis Cloud 通常会给你两种连接信息:
- 普通 TCP 端口
- TLS/SSL 端口
如果你拿的是普通端口,就不能加: ssl=True。
如果是 TLS 端口,必须加:ssl=True
2)确认你是不是应该用 rediss://
比如我开始使用的是
index.connect("redis://default:password@host:port")
如果是 SSL/TLS,应该改成:
index.connect("rediss://default:密码@host:port")
注意是:
redis:// = 非 SSL
rediss:// = SSL/TLS
这个可以在Redis CLI中确认。
import redis
import os
import numpy as np
from openai import OpenAI
from redisvl.index import SearchIndex
from redisvl.query import VectorQuery
from redisvl.utils.vectorize import HFTextVectorizer
import dotenv
dotenv.load_dotenv()
# =========================
# 1. 连接 Redis Cloud
# =========================
r = redis.Redis(
host="redis-19613.c256.us-east-1-2.ec2.cloud.redislabs.com",
port=19613,
username="default",
password="......",
decode_responses=True,
)
# 测试连接
print("PING:", r.ping())
# =========================
# 2. 向量化模型
# =========================
vectorizer = HFTextVectorizer(model="sentence-transformers/all-MiniLM-L6-v2")
vector_dims = vectorizer.dims
# =========================
# 3. 创建 RedisVL 索引
# =========================
schema = {
"index": {
"name": "rag_demo_index",
"prefix": "doc"
},
"fields": [
{"name": "text", "type": "text"},
{
"name": "text_embedding",
"type": "vector",
"attrs": {
"dims": vector_dims,
"distance_metric": "cosine",
"algorithm": "hnsw",
"datatype": "float32"
}
}
]
}
index = SearchIndex.from_dict(schema)
index.set_client(r)
index.create(overwrite=True)
# =========================
# 4. 写入数据到 Redis
# =========================
documents = [
"Redis 是一个开源的内存数据存储,用作数据库、缓存、流引擎和消息代理。",
"检索增强生成(RAG)是一种技术,它将神经网络语言模型与外部知识检索系统结合起来。",
"RedisVL 是一个专门为 AI 和 LLM 应用程序设计的 Redis 向量数据库客户端库。"
]
data = []
for i, doc in enumerate(documents, start=1):
embedding = np.array(vectorizer.embed(doc), dtype=np.float32).tobytes()
data.append({
"id": f"doc:{i}",
"text": doc,
"text_embedding": embedding
})
index.load(data)
print("数据已写入 Redis Cloud")
# =========================
# 5. 从 Redis 读取测试
# =========================
print("当前 Redis keys:", r.keys("*"))
# ==========================================
# 向量检索 (Retrieval)
# ==========================================
query_text = "请问什么是 RedisVL?"
print(f"\n用户提问: '{query_text}'")
# 对用户的查询也进行向量化
query_embedding = vectorizer.embed(query_text)
# 构建向量搜索查询,检索最相关的 2 条文档
query = VectorQuery(
vector=query_embedding,
vector_field_name="text_embedding",
return_fields=["text"],
num_results=2
)
# 执行查询
results = index.query(query)
retrieved_texts = [result["text"] for result in results]
context = "\n".join(retrieved_texts)
print("\n[检索到的上下文]:")
print(context)
# ==========================================
# 大模型生成回答 (Generation)
# ==========================================
# 此处以 OpenAI 为例。如果是本地大模型可以使用 ollama 或 vLLM。
# 请确保你的环境变量中设置了 OPENAI_API_KEY
print("\n[LLM 最终回答]:")
client = OpenAI(
# 如果没有配置环境变量,请用阿里云百炼API Key替换:api_key="sk-xxx"
api_key=os.getenv("aliyun_api_key"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
# 结合上下文构造提示词
prompt = f"请利用以下上下文信息来回答用户的问题。\n\n上下文:\n{context}\n\n用户问题: {query_text}\n回答:"
response = client.chat.completions.create(
model="qwen3-max",
messages=[
{"role": "system", "content": "你是一个有用的、专业的 AI 助理。"},
{"role": "user", "content": prompt}
]
)
print(response.choices[0].message.content)
输出:
数据已写入 Redis Cloud
当前 Redis keys: ['doc:01KPZSJDBRQ8AT5TC8P0FW6Q25', 'doc:01KPZSJDBRQ8AT5TC8P0FW6Q24', 'doc:01KPZT0633GR69ND5F9AXQZEGZ', 'doc:01KPZSNJ7MM4K96S37WNYDP393', 'doc:01KPZSNJ7MM4K96S37WNYDP392', 'doc:01KPZT0633GR69ND5F9AXQZEH0', 'doc:01KPZSNJ7MM4K96S37WNYDP391', 'doc:01KPZT0633GR69ND5F9AXQZEGY', 'doc:01KPZSJDBRQ8AT5TC8P0FW6Q23']
用户提问: '请问什么是 RedisVL?'
[检索到的上下文]:
RedisVL 是一个专门为 AI 和 LLM 应用程序设计的 Redis 向量数据库客户端库。
RedisVL 是一个专门为 AI 和 LLM 应用程序设计的 Redis 向量数据库客户端库。
[LLM 最终回答]:
RedisVL 是一个专门为 AI 和大语言模型(LLM)应用程序设计的 Redis 向量数据库客户端库。它简化了在 Redis 中存储、索引和检索向量数据的过程,帮助开发者高效构建基于向量搜索的 AI 应用。
Redis的数据是存在内存中的,它和传统内存存储区别¶
Redis 作为内存数据库,数据默认存储在内存中,断电或服务重启会导致数据丢失。为了解决这个问题,Redis 提供了两种核心的持久化机制:RDB(快照) 和 AOF(日志)。
你可以用一句话概括它们的区别: * RDB 就像是给数据“拍照片”(记录某个时间点的数据状态)。 * AOF 就像是“记流水账”(记录每一次修改数据的操作)。
1.RDB (Redis Database) —— 快照模式
RDB 是 Redis 默认的持久化方式。它的核心思想是在指定的时间间隔内,将内存中的数据集快照写入磁盘,生成一个二进制文件(通常命名为 dump.rdb)。 核心原理 * 触发机制:可以通过配置自动触发(如 save 900 1,表示 900 秒内至少有 1 个键变化就触发),也可以手动执行 SAVE 或 BGSAVE 命令。 * 后台执行与写时复制 (COW):为了不阻塞主线程,Redis 通常使用 BGSAVE。它会 fork 一个子进程,利用操作系统的写时复制(Copy-On-Write)技术,让子进程在后台将内存数据写入临时文件,最后原子替换旧的 RDB 文件。这意味着在快照生成期间,主进程依然可以处理客户端请求。
优缺点分析
| 维度 | 优势 | 劣势 |
|---|---|---|
| 性能 | 对性能影响极小,主进程只负责 fork 子进程,不进行磁盘 I/O。 | 在数据量极大时,fork 操作可能导致主进程短暂阻塞(毫秒级)。 |
| 恢复速度 | 极快。加载二进制文件直接还原内存,无需解析命令。 | 无。 |
| 数据完整性 | 文件紧凑,适合备份和灾难恢复。 | 会丢失数据。只能恢复到上一次快照的时间点,两次快照之间的数据会丢失。 |
| 文件体积 | 文件体积小,经过压缩,适合传输。 | 无。 |
2.AOF (Append Only File) —— 日志模式
AOF 的核心思想是将 Redis 执行的每一条写命令(如 SET、INCR)以文本协议的形式追加到日志文件末尾(通常命名为 appendonly.aof)。重启时,通过重新执行这些命令来恢复数据。 核心原理 * 写后日志:Redis 先执行命令,再将命令追加到 AOF 缓冲区,最后根据策略刷入磁盘。 * 刷盘策略 (appendfsync): * always:每条命令都立即同步到磁盘。最安全(几乎不丢数据),但性能最差。 * everysec(推荐):每秒同步一次。兼顾了性能和安全,最多丢失 1 秒数据。 * no:由操作系统决定何时同步。性能最好,但数据最不安全。 * AOF 重写 (Rewrite):随着时间推移,AOF 文件会越来越大(例如对同一个键执行了 100 次 INCR)。Redis 会在后台启动子进程,根据当前内存数据的最新状态,生成一个精简的新 AOF 文件(上述 100 次操作会被合并为一条命令),替换旧文件。
优缺点分析
| 维度 | 优势 | 劣势 |
|---|---|---|
| 数据完整性 | 极高。配合 everysec 策略,最多只丢 1 秒数据;配合 always 可做到不丢。 | 无。 |
| 可读性 | 文件是文本格式,可读性强,甚至可以手动修改修复。 | 无。 |
| 恢复速度 | 较慢。需要逐条重放命令,数据量大时恢复慢。 | 无。 |
| 文件体积 | 文件体积通常比 RDB 大。 | 即使有重写机制,文件依然较大,占用更多磁盘 I/O。 |
3.总结与最佳实践 在实际生产环境中,我们通常不会二选一,而是根据需求组合使用。
RDB vs AOF 对比
| 特性 | RDB (快照) | AOF (日志) |
|---|---|---|
| 记录方式 | 全量数据快照(二进制) | 增量操作日志(文本协议) |
| 数据安全性 | 低(可能丢失几分钟数据) | 高(最多丢失 1 秒) |
| 恢复速度 | 快 | 慢 |
| 适用场景 | 冷备、灾难恢复、主从同步 | 核心业务数据、高可靠性要求 |
💡 推荐方案:混合持久化 (Redis 4.0+) 为了兼顾 RDB 的快速恢复 和 AOF 的数据安全,Redis 4.0 引入了混合持久化。 * 原理:在进行 AOF 重写时,不是生成纯文本的 AOF 文件,而是将当前内存数据以 RDB 二进制格式 写入文件前半部分,将重写期间产生的增量命令以 AOF 文本格式 追加到文件后半部分。 * 优势: 恢复快:加载前半部分的 RDB 数据非常快。 数据全:后半部分的 AOF 日志保证了最后一次快照后的数据不丢失。 配置简单:只需在配置文件中开启 aof-use-rdb-preamble yes。
生产环境建议:
同时开启 RDB 和 AOF,并使用混合持久化模式,AOF 刷盘策略设为 everysec。这样既能保证数据尽可能不丢失,又能确保在故障重启时以最快速度恢复服务。
(everysec 策略的核心机制是:每秒将缓冲区中的数据同步到磁盘一次。 具体来说,当 Redis 执行写操作时,会先将命令写入内存中的 AOF 缓冲区。然后,一个后台线程会每隔一秒钟调用一次操作系统的 fsync 函数,将这个缓冲区里的所有数据真正写入到磁盘的 AOF 文件中。 everysec 是在性能和数据安全性之间做出的一个折中方案,也是 Redis 官方推荐的默认配置。)
参考¶
https://cloud.tencent.com/developer/article/2653346
一文搞懂redis的所有知识点:https://zhuanlan.zhihu.com/p/663851226
https://blog.csdn.net/The_Thieves/article/details/149205091