场景题一

参考:

海量数据处理思路

一 TOP-K问题

(1)TOP=K问题=  
        在海量数据中找出出现次数最大 数值最大的前k个数
(2) 常规方法  
        分冶    +
        hash || Trie (用于 去重|| 检测频率)    +
        堆排序 

1. TOP-K 数值问题

    (1) 10000个数据 建立 size=10000  小顶堆 
    (2) 继续添加剩余数据, 
             val> 堆顶(最小数) ,则val替换堆顶,并调整堆为小顶堆
             val< 堆顶,则跳过
    
    (3) heap.size=10000 , 堆调整次数 = 十亿
        时间复杂度 = Om (初始建堆)+  Onlogm = Onlogm
    核心
    (4) 优化  冶:处理内存不足问题
             十亿数据存储在1000个文件中
            通过堆排序 将每个文件中10^6数据挑选出 10000个最大数据 
            将数据合并 ,通过快速排序获得前10000大的数据

2. TOP-K 频率问题

(1) 分冶 通过 hash 10^9 个数据 存储在多个文件中     // 同一hash值的 元素 
(2) 通过 hash || Trie(针对String) 统计重复频率,再通过堆排序选取每个文件中频率前10000的元素,建一个结构体作为堆结点元素
(3) 合并结果,再次通过hash || Trie统计频率,进行堆排序

二. 海量数据中 重复字符串 = 布隆过滤器

1. 布隆过滤器

k个哈希函数,一个大小为kn的位数组,n是value个数,每个value元素分别使用这k个哈希函数计算出k个位下标,把位数组中这k个位下标都置为1,在把所有元素都加入到这个位数组中后,如果要判断某个元素是否存在于这个value集合中,只需把这个要判断的元素根据k个哈希函数计算出k个为位下标后,判断维数组中这k个下标的元素,如果不是全为1,说明这个元素不存在,否则是可能存在。之间存在误判。
eg: 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
如果用byte数组,50亿 = 5 * 0.93 * 2^30 = 4.65G,如果用bit数组,50亿 = 4.65G / 8 = 0.58G
  (1)    n个元素的位图 占用nbit
    (2)     一个val 通过多个 hash函数生成多个hash
    (3)     每个hash值对应的 bit1 
    (4)     当输入数据量很大,布隆过滤器长度较小时 容易误判

三. 海量数据中 重复数字 = 位图

① 去重

一个位数组,每一个bit为表示一个数字,数组的长度取决于数字的最大值。把每个元素对应的为都置位1,最后遍历一次这个位数组,就可以得到去除重复之后的元素集合。

② 找出不重复元素的个数

2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。
    将bit-map扩展一下,用2bit表示一个数即可,0表示未出现,1表示出现一次,2表示出现2次及以上,在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则保持不变。
    1. N个数中,寻找未出现的数 
    2. 构建 bit[] 数组, size=N 
            内存受限时, 
            分区间检测,
            [2M , 3M]中元素数量少于M
            则不存在元素出现在[2m,3m]范围内
    3. 每当出现一个数据,则bit1 

必读

海量数据处理面试题集锦
教你如何迅速秒杀掉:99%的海量数据处理面试题

大数据类场景题

1、10亿个数值,找最大的一万个

设置一个buf,固定size,每次读一个buf大小的文件,维持一个大小为1万的小顶堆,遍历效率是o(nlogK)
大数的问题,你应该计算一下这个数组整体大小,然后询问数据是否重复,如果重复,先对文件hash,然后保存不同文件。

2、1亿个正整数,范围是0-42亿。求出现次数是2的数字,空间复杂度

32位机器最大能表示的数字是42亿9千多万。
将bit-map扩展一下,用2bit表示一个数即可,0表示未出现,1表示出现一次,2表示出现2次,3表示出现3次即以上,在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则将其置为3;如果是3,则保持不变。
42亿 * 2 = 86亿  = 86 * 10^8 = 8G, 所以空间开销为8G

3、2g内存,要求一个10g文件的中位数

4、有一个IP地址库,假设有几十万条ip,如何判断某个ip地址是否在这个库中?

思路一:分治法,将ip地址根据前三位分成256份,然后看这个ip地址对应的网段,只比对这个网段里面是否有这个ip,当然还可以继续分下去,根据数据量来决定分成多少份。
思路二:位图,将每一条ip对应位图中的一个位,2^32次方(42亿多)个数据只需要512M空间。可以实现O(1)的时间搜索,O(n)的时间存储。

5、一个5T的文件,里面全是id,1-10^9 ,如何计算不同id的个数?

思路一:哈希到不同的文件,再逐个文件内找不同的。
思路二:使用redis的HyperLoglog可以大致估算出不同id的个数。

其他场景题

1、一个每秒只能处理10w请求的系统,突然有50w的请求过来了,怎么处理使得这个系统不发生异常

阻塞队列
降级控制:就是对每一个任务设置一个级别,优先处理级别高的,级别低的任务的话可能价值不高或者没有价值,所以可能不执行或者稍后执行

作者:星__尘来源:牛客网

2、扫码登录是如何实现的?

3、B+树和红黑树

红黑树和一般的平衡二叉树,增、删、改、查的过程和效率、时间复杂度https://www.cnblogs.com/ArleneZhangfj/articles/10067570.html

4、让你设计一个微信发红包的api,你会怎么设计,不能有人领到的红包里面没钱,红包数值精确到分。

传入参数有总钱数,分的份数,随机分还是等分。先判断钱数能不能分那么多份,这个直接用总钱数>=0.01*份数判断就可以了。然后根据分发策略,选择随机还是等分,随机的话就给 1到总钱数-(总份数-1)*0.01 的随机数(总钱数以分为单位),等分的话直接除判断能不能除开,有余数就将余数加到最后一份里面。

5、需求:谁关注了我,我关注了谁,谁与我互相关注。表该如何设计,索引怎么建。查询语句怎么写

1、使用mysql实现

粉丝关注表使用四列,主键id,userId,fansId,是否互相关注。用两行数据来保存互相的关注关系,这样查询起来更方便,用空间换时间。
主键有主键索引,剩下的字段不适合建索引,因为字段重复太多。

2、使用redis来实现

因为这个表的字段太少,所以考虑使用redis来实现。用一个set存储每个用户的关注列表和粉丝列表,关注列表的键是“follow:" + 当前用户id,  粉丝列表的键是”当前用户的id" + "follow", 这样很容易就能得到某个用户的所有粉丝和关注的人,相互关注的只需让两个set取交集即可。

6、分布式多个机器生成id,如何保证不重复?

1.snowflake方案

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。
优点
1.毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
2.不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。
3.可以根据自身业务特性分配bit位,非常灵活。
缺点
强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。

2.用Redis生成ID:

因为Redis是单线程的,也可以用来生成全局唯一ID。可以用Redis的原子操作INCR和INCRBY来实现。
此外,可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis,可以初始化每台Redis的值分别是1,2,3,4,5,步长都是5,各Redis生成的ID如下:
A:1,6,11,16
B:2,7,12,17
C:3,8,13,18
D:4,9,14,19
E:5,10,15,20
这种方式是负载到哪台机器提前定好,未来很难做修改。3~5台服务器基本能够满足需求,都可以获得不同的ID,但步长和初始值一定需要事先确定,使用Redis集群也可以解决单点故障问题。
另外,比较适合使用Redis来生成每天从0开始的流水号,如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。
优点:
1)不依赖于数据库,灵活方便,且性能优于数据库。
2)数字ID天然排序,对分页或需要排序的结果很有帮助。
缺点:
1)如果系统中没有Redis,需要引入新的组件,增加系统复杂度。
2)需要编码和配置的工作量较大。

7、LRU算法知道吗,怎么实现的?

LRU算法:最近最少使用算法,常用于进程调度,缓存淘汰,内存页面置换等场景。
使用LinkedHashMap可以实现,相对于HashMap,增加了双向链表,用于记录节点之间的先后顺序。LinkedHashMap的构造函数提供了一个参数accessOrder,这个参数可以指定链表是按照插入顺序排队还是按照访问顺序排队。参数为true时,就是按照访问顺序(插入,查询)排队,每次访问后这个节点就会被放到链表头,而长时间不被访问的节点逐渐就到了列表尾部,当需要淘汰时,就将链表尾部的节点抛弃。

8、数据库连接池怎么设计?

需要考虑的问题:
  1. 限制连接池中最多、可以容纳的连接数目,避免过度消耗系统资源。
  2. 当客户请求连接,而连接池中所有连接都已被占用时,该如何处理呢?一种方式是让客户一直等待,直到有空闲连接,另一种方式是为客户分配一个新的临时连接。
  3. 当客户不再使用连接,需要把连接重新放回连接池。
  4. 连接池中允许处于空闲状态的连接的最大项目。假定允许的最长空闲时间为十分钟,并且允许空闲状态的连接最大数目为5,
那么当连接池中有n个(n>5)连接处于空闲状态的时间超过十分钟时,就应该把n-5个连接关闭,并且从连接池中删除,这样才能更有效的利用系统资源。

其他场景题

场景分析题:如果让你实现一个用户在另一台手机上登录微信后把他之前登录的那台手机上微信号顶掉你该怎么设计?说下你的思路

情景分析题:如果让你来实现一个对高考成绩的分类下的前100名成绩你该怎么实现?说说你的思路(我也不知道对不对 我答的是使用hash函数将不同科目的成绩分配到不同的文件然后在使用堆排序或者快排求解topk问题)

10亿大数加和,怎么写,我知道怎么多线程分别加和,但不知道什么数据结构可以存储每个线程的和,我说了String,面试官说太慢了,好像用Bigint也不够
设计一个错误类,输入范围内的整数,返回一个错误码。写了个类,但没想到怎么处理这个输入范围。
posted @ 2020-12-19 15:25  Lucky小黄人^_^  阅读(1661)  评论(0编辑  收藏  举报