在技术领域有一句经典话:程序=算法+数据结构。这意味着一个好的程序员往往要在算法与数据结构上有扎实的功底。这也是为何各个国内外大厂在面试时一定会考核这个领域。随着时代的发展,算法与数据结构的定义也在发生演变,早期的算法与数据结构主要针对于单机情况,例如经典的哈希,二叉树,折半查找等。但在互联网和大数据时代,有很多对应问题,经典算法已经解决不了,因为对于经典算法而言,它有一个潜在的要求就是数据能全部装入内存,但在大数据情况下,数据根本不能一次性装入内存,因此仅仅掌握经典算法是通不过互联网大厂的面试考核的。
如果你有过大厂面试经验,你会发现他们很多算法面试题的基本前提就是高并发和海量数据,如果你在设计解题思路时没有考虑这两点,那么通过的机会就很渺茫。在多年的发展积累后,在海量数据和高并发要求下,一套相应的,不同与经典的算法与数据结构体系已经诞生,两者之间的区别就如同经典牛顿力学和量子力学的区别。
由此我想利用一个专题,把我所了解的,用于高并发和海量数据的算法和数据结构讲解出来,这样能跟各位同行一起探讨学习以便共同进步。我们看一个具体的应用问题,那就是如何快速获得给定年龄区间的微信用户数量,例如给定[25,35],我们如何把处于这个年龄段的微信用户找出来。最简单的当然是把所有用户遍历一遍,然后遇到落入给定区间的用户就把计数加1,问题在于微信的用户量有十亿以上,单单过一遍都需要很长的时间,而且用户资料不可能全部存放在内存中,因此遍历时需要多次读取磁盘,于是又会进一步降低统计速度。
解决这个问题的一种有效算法和数据结构叫Count-Min Sketch。它最早用于在海量数据中快速获取数量个数位于前k的数据点,例如获取亚马逊网站上购买量前十的书籍或是在美团中购买量位于前十的食品品类。这类问题可以抽象为所谓的heavy hitters问题:给定一个参数k,对于包含N个元素的数组(N的量级在亿以上),如何快速找出重复次数超过N/k的元素。经典算法下的处理办法就是使用哈希表,每拿到一个元素就将其哈希到给定位置,将给定位置里的计数加一。但假设数值有十亿个不同的数,那么我们就需要将他们全部存储在内存中,如此一来我们解决问题的成本就会非常高。
在海量数据和高并发下,基本的处理思路就是不求精确解,但求近似解,只要我们把结果的误差控制在合理范围内即可,在后面你会看到,几乎所有用于高并发和海量数据的算法都是这个特征。对heavy hitter问题,我们会给定一组参数(,k),要求找到的元素,其重复次数至少有N/k -
N,我们看看如何使用Count-min sketch算法来满足这个要求。
算法支持两种操作,分别是update和estimate, 假设在时间t,我们收到一组元素(,
),
表示时间t时出现的元素,
对应它的计数,update操作就会讲元素
的总出现次数加上
.那么estimate操作将给出元素
到时刻t为止出现的总次数。estimate返回给定元素的出现次数只会多不会少,在给定概率内,多出的数量不会超过
N,我们看看其对应的数据结构。
Count-min sketch在数据结构上对应一个二维矩阵,它有d行和w列,其中每个元素都初始化为0.然后选取d个不同的哈希函数,
,每个哈希函数的输出范围在[0...w-1],每个哈希函数分别对应二维数组的一行。在执行update操作时,我们分别用每个哈希函数对元素进行运算得到输出结果,将输出结