在业务中,我须要给每一个用户保存1w条浏览记录,以后每一次的返回值都要和历史记录作一个去重,即保证用户不会重复看到同一篇文章.redis
这个需求有两个比较麻烦的地方:算法
每一个用户1w条,10w用户就是10亿条数据,应该保存在哪里呢?sql
Redis?哪里有那么大内存给你用.数据库
Hbase?Hbase我不太了解具体原理,听说每次全量查询有点慢啊(后来听大佬说这点数据无压力的).数组
Mysql?却是能存下这么多,可是太影响性能了.缓存
这个需求对即时性要求仍是比较高的,用户两次刷新的间隔可能只有几秒钟,在此期间就要完成历史数据的添加以及过滤.安全
每次返回用户10条数据,每一条都须要和数据库
中的1w条作比对,听起来效率就不好的样子.网络
在大佬的推荐下,我去了解了一下布隆过滤器,最后初步使用布隆过滤器+Redis+Hbase完成了一个版本,效率和空间占用都还能够.函数
如下摘自维基百科:性能
布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它其实是一个很长的二进制向量和一系列随机映射函数。布隆过滤器能够用于检索一个元素是否在一个集合中。它的优势是空间效率和查询时间都远远超过通常的算法,缺点是有必定的误识别率和删除困难。
说直白一点就是:布隆过滤器用本身的算法,实现了快速的检索一个元素是否在一个较大的元素列表
之中.
当一个元素被加入集合时,经过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,咱们只要看看这些点是否是都是1就(大约)知道集合中有没有它了:若是这些点有任何一个0,则被检元素必定不在;若是都是1,则被检元素极可能在。这就是布隆过滤器的基本思想。
假设咱们如今得到了一个size=10000的布隆过滤器,分配给咱们的实际上是10000个二进制位,假设k=8
,那么当新添加huyanshi
这个元素时,经过8个不一样的hash函数
,能够拿到8个index值,假设为1,2300,222,11...
,咱们就将这8个index为下标的位置,置为1.
当咱们想要检索huyanshi
是否存在时,再次用8个hash函数得到8个index,若是这8个index的位置都为1,那么这个元素就很可能存在.若是其中有一位为0,则该元素必定不存在.
注意上面的可能加粗了,下面就要说优缺点了.
根据优缺点,咱们能够分析出他的使用场景,那么就是的正确率要求不是100%,同时存在海量的数据集.
布隆过滤器做为一个成熟的过滤器,应该学会实现本身了.
啊,不对,是网上有许多的简易版实现,代码不到100行就能够,所以这里不贴代码了.
我在项目中使用了google guava项目下的BloomFilter,挺好用的.
hbase负责存储用户浏览记录的原始数据,只保存用户浏览的文章的id或者url,这里以id为例.
经过范围查询能够得到name:huyanshi,history=[1,2,4,5,6]
格式的数据.
在这里面使用redis,主要是考虑到,针对活跃用户,及频繁刷新的用户,每次请求都全量从Hbase拉取数据,而后构造布隆过滤器,即时Hbase扛得住,我以为这个构造过滤器的时间也太长了.所以使用redis对过滤器进行缓存.
在redis中存储序列化后的布隆过滤器对象,时间为30分钟,30分钟内用户若是再次访问,直接从redis中获取过滤器,而后进行过滤操做.
主要是添加以及查询两个操做,从hbase拿到数据以后,构造过滤器,而后对当前返回的10条内容进行判重.以后将新的10条内容加入过滤器,再次写入redis.
很久没画图了,,,慌得一批.
完.
以上皆为我的所思所得,若有错误欢迎评论区指正。
欢迎转载,烦请署名并保留原文连接。
联系邮箱:huyanshi2580@gmail.com
更多学习笔记见我的博客------>呼延十