←←←←←←←←←←←← 快!点关注
背景
最近工作上有个类似需求是: 现有约3亿条数据词典存在于一个csv文件A中,作为数据源。对于 用户输入的任意单词M,需要快速的在A中匹配M单词是否存在。(A文件约3G大小左右,总行数三亿)
拿到这个需求,你的第一想法怎么做呢?
正常思路可能是:
- 将csv文件A导入某关系型数据库。
- sql查询按M匹配。
上面的方式有个明显的缺点是:慢!
3亿多行的数据,即便是建好索引进行检索,匹配到也得话不少时间(笔者没亲自试过,感兴趣的朋友可以自行测试测试,理论上快不起来的)。
目前能 在时间复杂度和空间复杂度上达到最佳的方案,恐怕就是Bloom Filter了, 维基地址:Bloom Filter
此处给不太了解Bloom Filter的读者看,熟悉的朋友直接看下一节。
本文场景Bloom Filter 使用思路解释:
假设申请了一段bit位大数组(即数组中的元素只能是一个bit位,1或0,默认元素值都为0)
将csv文件A中的每个单词,经过多个hash函数进行hash运算之后得到在大数组中对应的多个下标位置
将步骤2中得到的多个下标位置的bit位都置为1.
对于用户输入的任意单词M,按照2的步骤得到多个下标位置,其对应大数组中的值全部为1则存在,否则不存在。
方案选型
实现Bloom Filter
的方法很多,有各种语言版本的,这里为了真切感受一下算法的魅力,笔者这里决定用java 代码徒手撸了!
另一方面,考虑到分布式应用的需要,显然在单机内存上构建Bloom Filter
存储是不太合适的。 这里选择redis
。
redis有以下为操作,可以用于实现bloomfilter:
redis> SETBIT bit 10086 1
(integer) 0
redis> GETBIT bit 10086
(integer) 1
redis> GE