📘 1. Redis 简介
Redis(Remote Dictionary Server)是一个开源的内存数据结构存储系统,可以用作数据库、缓存和消息中间件。
什么是 Redis?
Redis 是一个基于键值对(Key-Value)的内存数据库,它支持多种数据结构,如字符串、哈希、列表、集合和有序集合。
Redis 以其高性能、丰富的数据结构和强大的功能而闻名,广泛应用于缓存、会话存储、排行榜、实时分析等场景。
Redis 的核心特点
- 内存存储:所有数据存储在内存中,访问速度极快
- 丰富数据类型:支持字符串、哈希、列表、集合、有序集合等
- 原子操作:所有操作都是原子的,保证数据一致性
- 持久化支持:RDB 和 AOF 两种持久化方式
- 主从复制:支持数据复制,提高可用性
- 高可用:支持哨兵和集群模式
应用场景
⚡ 缓存系统
作为数据库查询结果的缓存,减轻数据库压力
⬇️ 2. 安装与配置
Linux/Mac 安装
# 使用 Homebrew 安装(Mac)
brew install redis
# 使用 apt 安装(Ubuntu/Debian)
sudo apt-get install redis-server
# 使用 yum 安装(CentOS/RHEL)
sudo yum install redis
启动 Redis
# 启动 Redis 服务器
redis-server
# 使用配置文件启动
redis-server /path/to/redis.conf
# 连接到 Redis 客户端
redis-cli
Docker 安装
# 拉取 Redis 镜像
docker pull redis
# 运行 Redis 容器
docker run -d -p 6379:6379 --name my-redis redis:latest
📖 3. 基础概念
键(Key)
Redis 中的键是二进制安全的,可以使用任何字符串作为键名。通常建议使用有意义且简洁的键名。
键命名建议:
- 使用冒号分隔不同层级:
user:1001:profile
- 保持键名简洁但有意义
- 避免使用过长的键名
值(Value)
Redis 支持多种数据类型的值,每种类型都有其特定的用途和操作命令。
数据库
Redis 默认支持 16 个数据库(索引 0-15),可以使用 SELECT 命令切换数据库。
# 切换到数据库 1
SELECT 1
# 查看当前数据库的键数量
DBSIZE
💬 5. 消息命令
Redis 提供了强大的消息传递机制,包括发布/订阅模式和流(Stream)数据结构,用于实现消息队列、实时通信等功能。
发布/订阅(Pub/Sub)
发布/订阅是一种消息通信模式,发送者(发布者)发送消息到频道,订阅者接收该频道的消息。
基础命令
# 发布消息到频道
PUBLISH channel "Hello World"
# 订阅一个或多个频道
SUBSCRIBE channel1 channel2
# 取消订阅
UNSUBSCRIBE channel
# 按模式订阅频道
PSUBSCRIBE news.*
# 按模式取消订阅
PUNSUBSCRIBE news.*
应用场景
- 实时通知:用户在线状态、系统告警等
- 实时聊天:多房间聊天室
- 日志聚合:多个服务发送日志到中央频道
- 事件广播:微服务间的事件通知
流(Stream)
Stream 是 Redis 5.0 引入的日志型数据结构,类似于 Kafka,用于消息队列和事件溯源。
基础命令
# 向流添加消息
XADD mystream * field1 value1 field2 value2
# 读取流中的消息
XRANGE mystream - +
# 消费者组读取消息
XREADGROUP GROUP group1 consumer1 COUNT 1 STREAMS mystream >
# 创建消费者组
XGROUP CREATE mystream group1 0
# 确认消息处理完成
XACK mystream group1 message_id
# 获取消费者组信息
XINFO GROUPS mystream
# 获取消费者信息
XINFO CONSUMERS mystream group1
Stream 特性
- 消息持久化:消息会被持久化,支持重放
- 消费者组:支持多个消费者协作处理消息
- 消息确认:支持 ACK 机制,确保消息被正确处理
- 消费者偏移量:记录每个消费者的消费进度
- 消息阻塞读取:支持阻塞读取新消息
应用场景
- 消息队列:可靠的消息传递和处理
- 事件溯源:记录系统状态变更历史
- 实时分析:实时数据处理和监控
- 任务队列:异步任务处理
列表作为消息队列
在引入 Stream 之前,Redis 列表常被用作简单的消息队列。
基础命令
# 生产者:发送消息到队列头部
LPUSH queue "message1"
# 消费者:从队列尾部取出消息
BRPOP queue 0 # 阻塞式读取
# 获取队列长度
LLEN queue
# 查看队列内容
LRANGE queue 0 -1
优缺点
优点:简单易用、高性能、支持阻塞读取
缺点:不支持消费者组、消息不可重放、缺少确认机制
消息队列模式对比
| 特性 |
Pub/Sub |
Stream |
List |
| 消息持久化 |
❌ |
✅ |
✅ |
| 消费者组 |
❌ |
✅ |
❌ |
| 消息确认 |
❌ |
✅ |
❌ |
| 消息重放 |
❌ |
✅ |
❌ |
| 实时性 |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
| 使用复杂度 |
⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐ |
最佳实践建议
- 简单通知:使用 Pub/Sub,适合实时通知场景
- 可靠消息传递:使用 Stream,支持消费者组和消息确认
- 简单队列:使用 List,适合轻量级消息队列
- 需要持久化和重放:优先选择 Stream
- 需要多个消费者协作:使用 Stream 的消费者组功能
💾 5. 持久化
RDB(Redis Database)
RDB 是 Redis 默认的持久化方式,它会在指定的时间间隔内生成数据集的时间点快照。
优点:文件紧凑,恢复速度快
缺点:可能会丢失最后一次快照后的数据
AOF(Append Only File)
AOF 记录服务器接收到的每一个写操作命令,并在服务器启动时重新执行这些命令来恢复数据。
优点:数据安全性更高,只丢失一秒数据
缺点:文件体积较大,恢复速度较慢
⚡ 6. 高级特性
事务
Redis 事务通过 MULTI、EXEC、DISCARD 和 WATCH 命令实现,保证一组命令的原子性执行。
MULTI
SET key1 value1
SET key2 value2
EXEC
发布/订阅
Redis 提供了发布/订阅功能,可以实现消息的广播和接收。
# 订阅频道
SUBSCRIBE channel
# 发布消息
PUBLISH channel "Hello Redis"
Lua 脚本
Redis 支持 Lua 脚本,可以在服务器端执行复杂的逻辑,保证原子性。
EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue
🔧 8. 插件编写
Redis 支持通过模块系统扩展其功能,开发者可以使用 C 语言或其他语言(通过 CFFI)编写自定义模块,添加新的数据类型、命令和功能。
Redis 模块系统概述
Redis 模块系统从 Redis 4.0 开始引入,允许开发者创建动态加载的扩展,扩展 Redis 的功能而无需修改 Redis 核心代码。
模块的优势
- 功能扩展:添加新的数据类型和命令
- 性能优化:使用 C 语言实现高性能功能
- 动态加载:无需重启 Redis 即可加载/卸载模块
- 隔离性:模块运行在独立的环境中,不影响 Redis 核心稳定性
开发环境准备
安装 Redis 源码
# 克隆 Redis 源码
git clone https://github.com/redis/redis.git
cd redis
# 编译 Redis
make
# 安装
sudo make install
安装开发工具
# Ubuntu/Debian
sudo apt-get install build-essential
# macOS
xcode-select --install
创建第一个 Redis 模块
模块基本结构
一个 Redis 模块需要包含以下关键组件:
- 模块初始化函数:在模块加载时调用
- 命令定义:声明模块提供的命令
- 命令实现函数:实现具体的命令逻辑
示例:简单的 Hello World 模块
// helloworld.c
#include "redismodule.h"
// 命令实现函数
int HelloCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 1) {
return RedisModule_WrongArity(ctx);
}
// 返回 "Hello, World!"
RedisModule_ReplyWithSimpleString(ctx, "Hello, World!");
return REDISMODULE_OK;
}
// 模块初始化函数
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (RedisModule_Init(ctx, "helloworld", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}
// 注册命令
if (RedisModule_CreateCommand(ctx, "hello", HelloCommand_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}
return REDISMODULE_OK;
}
编译模块
# 编译为动态库
gcc -I /usr/local/include/redis/ -fPIC -shared -o helloworld.so helloworld.c
# 或者使用 Redis 提供的 Makefile
make
加载和使用模块
# 启动 Redis 时加载模块
redis-server --loadmodule /path/to/helloworld.so
# 或者在运行时加载
redis-cli
127.0.0.1:6379> MODULE LOAD /path/to/helloworld.so
OK
# 使用自定义命令
127.0.0.1:6379> HELLO
"Hello, World!"
# 查看已加载的模块
127.0.0.1:6379> MODULE LIST
1) 1) "name"
2) "helloworld"
3) "ver"
4) (integer) 1
创建自定义数据类型
数据类型 API
Redis 模块可以创建全新的数据类型,需要实现以下接口:
- RDB 序列化/反序列化:数据持久化
- AOF 重写:命令日志记录
- 内存使用统计:INFO 命令支持
- 数据遍历:SCAN 命令支持
示例:简单的计数器数据类型
// counter.c
#include "redismodule.h"
#include
// 数据类型结构
typedef struct {
long long value;
} CounterObject;
// 创建新对象
CounterObject *createCounterObject(void) {
CounterObject *co = RedisModule_Alloc(sizeof(CounterObject));
co->value = 0;
return co;
}
// 释放对象
void freeCounterObject(CounterObject *co) {
RedisModule_Free(co);
}
// RDB 序列化
void counterRDBSave(RedisModuleIO *rdb, void *value) {
CounterObject *co = value;
RedisModule_SaveLongLong(rdb, co->value);
}
// RDB 反序列化
void *counterRDBLoad(RedisModuleIO *rdb, int encver) {
CounterObject *co = createCounterObject();
co->value = RedisModule_LoadLongLong(rdb);
return co;
}
// AOF 重写
void counterAOFRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) {
CounterObject *co = value;
RedisModule_EmitAOF(aof, "COUNTER.SET", "sl", key, co->value);
}
// 释放内存
void counterFree(void *value) {
freeCounterObject(value);
}
// 创建命令
int CounterCreateCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 2) {
return RedisModule_WrongArity(ctx);
}
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
CounterObject *co = createCounterObject();
RedisModule_ModuleTypeSetValue(key, CounterType, co);
RedisModule_ReplyWithSimpleString(ctx, "OK");
return REDISMODULE_OK;
}
// 设置命令
int CounterSetCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 3) {
return RedisModule_WrongArity(ctx);
}
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
return RedisModule_ReplyWithError(ctx, "Counter does not exist");
}
CounterObject *co = RedisModule_ModuleTypeGetValue(key);
long long value;
RedisModule_StringToLongLong(argv[2], &value);
co->value = value;
RedisModule_ReplyWithSimpleString(ctx, "OK");
return REDISMODULE_OK;
}
// 获取命令
int CounterGetCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 2) {
return RedisModule_WrongArity(ctx);
}
RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
return RedisModule_ReplyWithError(ctx, "Counter does not exist");
}
CounterObject *co = RedisModule_ModuleTypeGetValue(key);
RedisModule_ReplyWithLongLong(ctx, co->value);
return REDISMODULE_OK;
}
// 数据类型定义
RedisModuleType *CounterType;
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (RedisModule_Init(ctx, "counter", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}
// 注册数据类型
RedisModuleTypeMethods tm = {
.version = REDISMODULE_TYPE_METHOD_VERSION,
.rdb_load = counterRDBLoad,
.rdb_save = counterRDBSave,
.aof_rewrite = counterAOFRewrite,
.free = counterFree
};
CounterType = RedisModule_CreateDataType(ctx, "CounterType", 0, &tm);
if (CounterType == NULL) return REDISMODULE_ERR;
// 注册命令
if (RedisModule_CreateCommand(ctx, "counter.create", CounterCreateCommand, "write", 0, 0, 0) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}
if (RedisModule_CreateCommand(ctx, "counter.set", CounterSetCommand, "write", 0, 0, 0) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}
if (RedisModule_CreateCommand(ctx, "counter.get", CounterGetCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
return REDISMODULE_ERR;
}
return REDISMODULE_OK;
}
高级特性
通知和回调
模块可以注册回调函数来响应 Redis 事件:
// 注册键空间通知回调
RedisModule_SubscribeToKeyspaceEvents(ctx, REDISMODULE_NOTIFY_STRING, keyspaceNotificationCallback);
// 注册模块命令回调
RedisModule_SetCommandInfoCallback(ctx, commandInfoCallback);
数据类型遍历
为自定义数据类型实现 SCAN 支持:
// 实现 SCAN 遍历
void counterDigest(RedisModuleDigest *digest, void *value) {
CounterObject *co = value;
RedisModule_DigestAddLongLong(digest, co->value);
}
void counterFreeEffort(RedisModuleString *key, void *value) {
// 返回释放对象所需的"代价"
return 1;
}
集群支持
模块可以在集群环境中工作:
// 检查集群模式
if (RedisModule_GetClusterNodeInfo(ctx, ...) == REDISMODULE_ERR) {
// 集群模式处理
}
最佳实践
错误处理
- 始终检查 API 调用的返回值
- 使用 RedisModule_ReplyWithError 返回错误信息
- 在模块初始化时进行充分的参数验证
内存管理
- 使用 RedisModule_Alloc/RedisModule_Free 分配内存
- 实现正确的内存释放函数
- 避免内存泄漏
线程安全
- Redis 模块运行在单线程环境中
- 避免使用全局变量
- 正确处理并发访问
性能优化
- 尽量减少不必要的内存分配
- 使用 RedisModule_Yield 处理长时间运行的操作
- 合理使用 RedisModule_Call 调用其他 Redis 命令
调试和测试
使用 Redis 的测试框架
# 使用 Redis 的测试套件
./runtest --single unit/moduleapi
# 或使用 Redis 的模块测试工具
./runtest --single unit/type/set --valgrind
调试技巧
- 使用 RedisModule_Log 记录日志
- 使用 gdb 或 lldb 调试模块
- 使用 Valgrind 检测内存泄漏
发布和分发
模块打包
# 创建 Makefile
CFLAGS = -I$(REDIS_PATH)/src -fPIC
LDFLAGS = -shared
all: mymodule.so
mymodule.so: mymodule.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
文档和示例
- 提供清晰的 README 文档
- 包含使用示例和最佳实践
- 提供 API 文档
常用模块参考
- RedisJSON:JSON 数据类型支持
- RediSearch:全文搜索引擎
- RedisTimeSeries:时间序列数据
- RedisBloom:概率数据结构
- RedisGraph:图数据库
学习资源
🚀 7. 最新特性
Redis 7.x 新特性
Redis 7.x 版本引入了许多重要的新特性和改进,显著提升了性能和可用性。
🔥 函数(Functions)
Redis 7 引入了函数功能,这是 Lua 脚本的进化版本,提供了更好的性能和管理能力。
# 加载函数
FUNCTION LOAD "#!lua name=mylib \
local function myfunc(keys, args) \
return redis.call('GET', keys[1]) \
end \
redis.register_function('myfunc', myfunc)"
# 执行函数
FCALL myfunc 1 mykey
优势:更好的性能、持久化、函数库管理、版本控制
📊 Redis Stack
Redis Stack 是 Redis 的扩展模块,提供了现代应用所需的高级功能。
🔍 RedisJSON
原生 JSON 数据类型支持
⏱️ RedisTimeSeries
时间序列数据存储
📈 RedisBloom
概率数据结构(布隆过滤器等)
⚡ 性能优化
Redis 7 在多个方面进行了性能优化:
- 更快的列表操作:使用 ListPack 替代 QuickList
- 优化的哈希表:改进了哈希表的内存使用和性能
- 更高效的过期键清理:改进了过期键的扫描和删除机制
- 更好的集群性能:优化了集群槽的分配和迁移
🔐 安全增强
Redis 7 增强了安全性功能:
- ACL v2:改进的访问控制列表,支持更细粒度的权限管理
- TLS 1.3 支持:支持最新的 TLS 协议版本
- 改进的密码策略:更强的密码强度要求
📦 新数据结构
Redis 7 引入了一些新的数据结构改进:
- ListPack:更紧凑的列表编码,减少内存使用
- Stream 增强:改进了消费者组和消费者管理
- HyperLogLog 改进:更精确的基数估计
🛠️ 运维改进
Redis 7 提供了更好的运维工具和功能:
- 更完善的日志系统:结构化日志,支持 JSON 格式
- 改进的监控指标:更详细的性能指标统计
- 更好的调试工具:增强的命令和调试功能
- 配置热重载:支持部分配置的动态更新
🌐 客户端改进
Redis 7 对客户端协议进行了改进:
- RESP3 协议:更高效的协议,支持更多数据类型
- 客户端缓存:支持服务器辅助的客户端缓存
- 推送/拉取模式:改进的键空间通知机制
Redis 8.x 展望
Redis 8.x 将继续带来更多创新功能:
- 多线程架构:进一步改进并发性能
- 更好的云原生支持:优化的容器化和云部署
- AI/ML 集成:支持机器学习工作负载
- 持续的性能优化:针对大数据量的优化
🔎 10. RediSearch
RediSearch 是 Redis 的全文搜索引擎模块,为 Redis 提供了强大的搜索、索引和查询功能。
什么是 RediSearch?
RediSearch 是一个高性能的全文搜索引擎,基于 Redis 构建,支持中文分词、模糊搜索、聚合查询等高级功能。它可以在 Redis 中创建索引,对存储的数据进行快速搜索和检索。
RediSearch 的核心特性
- 全文搜索:支持文本搜索、短语搜索、通配符搜索
- 高性能:基于内存的索引,查询速度快
- 中文支持:内置中文分词器,支持中文搜索
- 聚合查询:支持分组、统计、排序等聚合操作
- 实时索引:数据变更时自动更新索引
- 高可用:支持 Redis 集群和主从复制
安装 RediSearch
使用 Docker 安装
# 拉取包含 RediSearch 的 Redis 镜像
docker pull redis/redis-stack-server:latest
# 运行容器
docker run -d -p 6379:6379 --name redis-stack redis/redis-stack-server:latest
使用源码编译
# 克隆 RediSearch 仓库
git clone https://github.com/RediSearch/RediSearch.git
cd RediSearch
# 编译模块
make setup
make build
# 加载模块到 Redis
redis-server --loadmodule ./build/search/redisearch.so
在运行时加载模块
# 连接到 Redis
redis-cli
# 加载 RediSearch 模块
MODULE LOAD /path/to/redisearch.so
# 查看已加载的模块
MODULE LIST
创建索引
基础索引创建
# 创建简单索引
FT.CREATE myindex ON HASH PREFIX 1 user: SCHEMA name TEXT age NUMERIC
完整索引配置
# 创建包含多种字段的索引
FT.CREATE products_idx ON HASH PREFIX 1 product: SCHEMA
title TEXT WEIGHT 5.0
description TEXT
price NUMERIC
category TAG
in_stock NUMERIC
created_at NUMERIC SORTABLE
索引字段类型
- TEXT:文本字段,支持全文搜索
- NUMERIC:数值字段,支持范围查询和排序
- TAG:标签字段,支持精确匹配和集合操作
- GEOSHAPE:地理形状字段,支持地理空间查询
- VECTOR:向量字段,支持向量相似度搜索
添加数据
使用 HSET 添加数据
# 添加用户数据
HSET user:1 name "张三" age 25 email "zhangsan@example.com"
HSET user:2 name "李四" age 30 email "lisi@example.com"
HSET user:3 name "王五" age 28 email "wangwu@example.com"
# 添加产品数据
HSET product:1 title "智能手机" description "高性能智能手机" price 3999 category "电子产品" in_stock 100
HSET product:2 title "笔记本电脑" description "轻薄便携笔记本" price 6999 category "电子产品" in_stock 50
HSET product:3 title "运动鞋" description "舒适耐穿运动鞋" price 599 category "服装" in_stock 200
搜索查询
基础搜索
# 简单文本搜索
FT.SEARCH myindex "张三"
# 搜索多个关键词
FT.SEARCH myindex "张三 OR 李四"
# 短语搜索
FT.SEARCH products_idx "智能手机"
高级搜索
# 带条件的搜索
FT.SEARCH products_idx "@title:智能 @price:[3000 5000]"
# 使用通配符
FT.SEARCH products_idx "@title:智*"
# 模糊搜索
FT.SEARCH products_idx "%智能%"
数值范围查询
# 价格范围查询
FT.SEARCH products_idx "@price:[500 1000]"
# 年龄范围查询
FT.SEARCH myindex "@age:[25 30]"
标签查询
# 单个标签查询
FT.SEARCH products_idx "@category:{电子产品}"
# 多个标签查询
FT.SEARCH products_idx "@category:{电子产品 | 服装}"
# 排除标签
FT.SEARCH products_idx "@category:{-配件}"
布尔查询
# AND 查询
FT.SEARCH products_idx "@title:智能 @category:{电子产品}"
# OR 查询
FT.SEARCH products_idx "@title:智能 | @title:电脑"
# NOT 查询
FT.SEARCH products_idx "@title:智能 -@category:{配件}"
# 复杂布尔查询
FT.SEARCH products_idx "(@title:智能 | @title:电脑) @price:[0 5000]"
排序和分页
# 按价格升序排序
FT.SEARCH products_idx "*" SORTBY price ASC
# 按价格降序排序
FT.SEARCH products_idx "*" SORTBY price DESC
# 分页查询
FT.SEARCH products_idx "*" LIMIT 0 10
# 排序和分页结合
FT.SEARCH products_idx "*" SORTBY price DESC LIMIT 0 10
聚合查询
基础聚合
# 按类别分组统计
FT.AGGREGATE products_idx "*" GROUPBY 1 @category REDUCE COUNT 0 AS count
# 计算平均价格
FT.AGGREGATE products_idx "*" REDUCE AVG 1 @price AS avg_price
复杂聚合
# 按类别分组,计算数量和平均价格
FT.AGGREGATE products_idx "*"
GROUPBY 1 @category
REDUCE COUNT 0 AS count
REDUCE AVG 1 @price AS avg_price
REDUCE SUM 1 @price AS total_price
SORTBY count DESC
过滤和排序
# 带过滤条件的聚合
FT.AGGREGATE products_idx "@category:{电子产品}"
GROUPBY 1 @category
REDUCE COUNT 0 AS count
REDUCE AVG 1 @price AS avg_price
# 多级排序
FT.AGGREGATE products_idx "*"
GROUPBY 1 @category
REDUCE COUNT 0 AS count
SORTBY count DESC avg_price ASC
中文分词
使用中文分词器
# 创建支持中文的索引
FT.CREATE articles_idx ON HASH PREFIX 1 article: SCHEMA
title TEXT
content TEXT LANGUAGE chinese
tags TAG
中文搜索示例
# 添加中文文章
HSET article:1 title "Redis 教程" content "Redis 是一个高性能的键值数据库" tags "数据库 缓存"
HSET article:2 title "搜索引擎" content "全文搜索引擎支持中文分词" tags "搜索 中文"
# 中文搜索
FT.SEARCH articles_idx "数据库"
FT.SEARCH articles_idx "中文分词"
FT.SEARCH articles_idx "@title:{Redis}"
索引管理
查看索引信息
# 列出所有索引
FT._LIST
# 查看索引详情
FT.INFO myindex
# 查看索引的字段
FT.PRODUCTS_IDX
删除索引
# 删除索引
FT.DROPINDEX myindex
# 删除索引及其关联的文档
FT.DROPINDEX myindex DD
重建索引
# 重建索引
FT.DROPINDEX myindex
FT.CREATE myindex ON HASH PREFIX 1 user: SCHEMA name TEXT age NUMERIC
性能优化
索引优化建议
- 合理选择字段:只为需要搜索的字段创建索引
- 使用字段权重:为重要字段设置更高的权重
- 限制结果数量:使用 LIMIT 分页返回结果
- 避免通配符开头的查询:影响性能
- 使用 SORTABLE 字段:提高排序性能
查询优化技巧
# 使用 NOCONTENT 只返回 ID,减少数据传输
FT.SEARCH products_idx "@title:智能" NOCONTENT
# 使用 RETURN 指定返回字段
FT.SEARCH products_idx "@title:智能" RETURN 2 title price
# 使用 SCORER 指定评分算法
FT.SEARCH products_idx "@title:智能" SCORER BM25
应用场景
电商搜索
功能:商品搜索、分类筛选、价格排序、关键词高亮
内容搜索
功能:文章搜索、全文检索、相关推荐
日志分析
功能:日志搜索、错误过滤、统计分析
用户搜索
功能:用户查找、条件筛选、实时匹配
RediSearch vs 传统搜索引擎
| 特性 |
RediSearch |
Elasticsearch |
| 性能 |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
| 部署复杂度 |
⭐⭐ |
⭐⭐⭐⭐ |
| 中文支持 |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
| 聚合查询 |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
| 内存占用 |
⭐⭐⭐ |
⭐⭐ |
| 实时性 |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
最佳实践
- 合理设计索引:根据查询需求设计索引结构
- 使用合适的字段类型:TEXT 用于文本,NUMERIC 用于数值,TAG 用于分类
- 控制索引大小:避免创建过多的索引字段
- 使用缓存:对热点查询结果进行缓存
- 监控性能:定期检查索引性能和查询响应时间
学习资源