📘 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

🎯 4. 数据类型

📝 字符串(String)

最基本的数据类型,可以存储任何形式的数据,包括文本、数字、二进制数据等。

SET key value GET key INCR key

#️⃣ 哈希(Hash)

键值对集合,适合存储对象。一个哈希可以包含多个字段和值。

HSET key field value HGET key field HGETALL key

📋 列表(List)

有序的字符串集合,支持在列表的两端进行插入和删除操作。

LPUSH key value RPUSH key value LRANGE key 0 -1

🔢 集合(Set)

无序不重复的字符串集合,支持集合间的交集、并集、差集操作。

SADD key member SMEMBERS key SINTER key1 key2

📊 有序集合(ZSet)

有序的字符串集合,每个元素都关联一个分数,支持按分数范围查询。

ZADD key score member ZRANGE key 0 -1 ZRANK key member

🎨 位图(Bitmap)

基于字符串类型的位操作,可以高效的进行位级别的操作。

SETBIT key offset value GETBIT key offset BITCOUNT key

📦 JSON(RedisJSON)

原生 JSON 数据类型支持,允许在 Redis 中存储、查询和操作 JSON 文档。需要 RedisJSON 模块。

JSON.SET key $ '{"name":"Redis","version":7}' JSON.GET key $ JSON.GET key $.name JSON.DEL key $.version JSON.ARRLEN key $.items

💬 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 数据类型支持

🔎 RediSearch

全文搜索引擎

⏱️ 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 用于分类
  • 控制索引大小:避免创建过多的索引字段
  • 使用缓存:对热点查询结果进行缓存
  • 监控性能:定期检查索引性能和查询响应时间

学习资源

📋 继续学习命令参考