系统设计 --- MongoDB亿级数据查询分表策略
- 背景
- Solution --- 分表
背景
使用audit log实现Audi Trail功能
- Audit Trail范围: 六个月
- 数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据
- 需要实现全文检索
- 按照时间倒序
- 因为license问题,不能使用ELK只能使用MongoDB
- 理想情况下,对于大量数据的全字段全文检索查询的最佳方案是ELK
挑战
- 要求一分钟之内前端返回结果
- 需要支持不同的查询条件
- 需要支持服务器端分页
- 需要支持服务器端排序(时间排序)
Mongo性能验证:
- Mongo单个Collection可支持500w条数据,超过
500w
条时,查询速度会变慢甚至超时(一分钟)
Solution — 分表
如何进行分表
- 因为是按照时间排序,所以可以按照数据的时间进行分表
- 一周的数据放进一个collection (一周的数据大概是300万-400万,刚好在500w的阈值之内)
如何写入
- 实现一个映射方法:输入一个年月日的时间可以映射成一个字符串, 使用这个字符串作为collection的名字
- 如
Map(2025-01-05) = "2025_Week_1"
如何进行分页查询:
查询条件:
pageSize = 100, pageNum = 2, startTime = 2024-06-08, endTime = 2024-10-10, operator = "Daniel" and message conatines "XYC"
step1: count (very expensive)
- 根据查询的起止时间,得到涉及哪些collections, for example
- collection1 (50条)
- collection 2 (60条)
- collection 3 (110条)
- collection 4 (20条)
- collection 5 (0条)
…
- 这里可以优化,把相同查询条件的count缓存起来
- 比如用户在前端点击下一页时往往使用的是同样的查询条件
step2: 查询
- 并发查询每个collection有多少符合条件的数据 (也就是operator = “Daniel” and message conatines “XYC”`)
- 根据paging的信息,计算出需要取多少数据,并进行抓取
- `pageSize = 100, pageNum = 2
- collection1 (50条)跳过
- collection 2 (60条) 跳过50条,抓取后10条
- collection 3 (40条) 抓取40条
- collection 4 (20条) 抓取10条
数据库交互次数
- 两次:count一次,实际查询一次