记一次关于查重逻辑的优化及流程、效果
背景
1000多个老师整理试题,分不同学科。估计初始阶段题量有10w左右。通过word形式导入到程序系统中。
但是,在制作试题的过程中,可能会出现重复的情况,造成其他影响。所以,需要做一个查重功能解决这个问题。
方案
首先‘查重’要考虑效果、效率的问题。
- 效果:
不是简单的字符串匹配,这个效果有点不好。采用了SimHash算法。通过去噪、去杂、分词、hash等过程,达到一个比较理想的对比效果。 -
效率:
题量少的时候,查询效率正常。当达到十万、百万级时,可能就会有效率问题。所以要加缓存或者MongoDB/ ES之类的,加快查询效率。最后采用最小堆算法处理最相近的5道题
处理逻辑
效率测试效果
下列是存到NoSql数据库中的数据结构,id为题号,hash为SimHash。循环比较当前题和哪些题最相近。
{
"subjectId":1,
"crList":"[
{\"id\":5984840,\"hash\":8065260974767954229},
{\"id\":5989000,\"hash\":10746764603123134457},
{\"id\":5989007,\"hash\":10746764603123134457},
{\"id\":5990047,\"hash\":8065260974767954229}
]"
}
注:这个json数据有个优化点,可以将id、hash替换为 k、v 减少存储的数据量。
10w条数据可以减少 100000 * 4 个存储空间。
本来刚开始是使用Redis进行存储的。针对于每个subjectId分A、B两块Redis缓存。A是某刻全量数据,B是最近500条新增、修改的数据。按照一定的规则\时间将B合并到A。防止A的频繁修改。
预估每个redis对象小于40MB,但是运维的要求是redis对象不能超过200KB。所以,就不能用redis了。换到了MongoDB。
MongoDB本地测试 (单条Document最大值只能存16MB)
单个知识点的数据(题+hash存储)
数据量 | MongDB单文档大小 | 删除时间 | 插入时间 | 读取时间 | hash比较处理 |
---|---|---|---|---|---|
400,000 | 15.5MB | 1s | 14s | 8s | 1~2s |
200,000 | 7.7MB | 1s内 | 7s | 1s | 1~2s |
10,000 | 0.38MB | 14 | 448 | 65 | 97 |
估计50,000,000个数据 占用小于 2个G。
再优化
- 增加caffeine本地缓存。
- 参数配置提取(
- 本地缓存时间
- SimHash规则(去除html、去除无效词[的、得、地等]、相似阈值等)
- 全量数据更新规则
)
后续
根据线上的使用情况,在进行后续调整
原创文章,转载请标明本文链接: 记一次关于查重逻辑的优化及流程、效果