聊聊倒排索引的使用场景和框架

之前面的时候遇到过这么个问题,有一批20w左右的数据要做缓存,每条数据主要是游戏信息,附带多个标签/游戏类型,现在要实现前端可以选择多个游戏类型, 接口返回相关游戏信息并且可以分页,这个该怎么实现。

1. 当初的想法

当时想到的是用Redis做缓存,把游戏的标签缓存到Redis中, 因为面试的是Go开发岗位,下面举例子我都用Go来实现。

1.1. 游戏接口定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package game

// Game 游戏数据模型
type Game struct {
	ID          int      `json:"id"`
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Tags        []string `json:"tags"` // 如: ["动作", "冒险", "多人"]
	Price       float64  `json:"price"`
	// 其他字段...
}

1.2. 缓存思路

1
2
3
4
5
6
7
8
9
// 1. 存储游戏详情
game:1 -> JSON序列化的游戏数据
game:2 -> JSON序列化的游戏数据

// 2. 标签索引集合
tag:动作 -> {1, 3, 5, 7, 10}      // 包含"动作"标签的游戏ID集合
tag:冒险 -> {1, 2, 5, 8, 12}
tag:多人 -> {1, 3, 7, 9, 15}
// ... 其他标签

1.3. 接口思路

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 根据标签查询并分页
package main
func (s *GameService) SearchByTags(ctx context.Context, tags []string, page, pageSize int) ([]*Game, int, error) {
    if len(tags) == 0 {
    return s.getAllGames(ctx, page, pageSize)
    }
    
    // 1. 获取标签的交集(即包含所有选中标签的游戏ID)
	
    // Redis SInterStore 计算交集
	
    // 2. 获取总数
	
    // 3. 分页获取游戏ID
    
    // 4. 批量获取游戏详情
    
    
    return 游戏列表, 总数, nil
}

之前也做过类似的功能,给用户打标签,多个标签形成用户画像,之后给这些用户推荐业务。
一开始没想起来这个就是属于倒排索引的使用,是面试回来后发记起这事,下面分享一些倒排索引的常用框架。

2. 倒排索引常用框架

  • Elasticsearch,这个众所周知,厉害是厉害,但是比较吃资源
  • Bleve(纯Go搜索引擎),适合嵌入到Go应用中
  • Typesense(高性能开源搜索),据说是比Elasticsearch更轻量、更快的搜索引擎

3. 框架选择

3.1. 场景1:需要最强性能

推荐:Elasticsearch

专门的搜索引擎,倒排索引优化到极致

支持复杂的布尔查询、评分、高亮等

分布式,可水平扩展

社区活跃,生态完善

3.2. 场景2:希望轻量级嵌入Go应用

推荐:Bleve

纯Go实现,无外部依赖

部署简单,单个二进制文件

适合中等数据量(百万级别)

与Go应用深度集成

3.3. 场景3:追求简单部署和高性能平衡

推荐:Typesense

比Elasticsearch更轻量

性能接近Elasticsearch

API更简单易用

安装部署简单

0%