ES
索引是怎么建立的?
我们是用索引模板创建的索引,每天或者每小时(看分索引的力度,一般是一天)当第一条数据插入时,会根据索引模板生成索引的mapping。如果没有设置索引模板也是可以插入数据,但是字段的类型是自动推断出来的,不是我们想要的结果。
也可以写定时脚本,每天自动生成后一天的索引mapping。
为什么要每天创建一个索引?
- 就像hive的分区表一样,查询数据时避免扫描全部的信息,提高查询效率。
- 增加es数据变化的灵活性。比如第二天需要增加字段,那么之前的mapping就不能用了。
分片数和副本数怎么设置的?
副本数设置为2,设置多了会占用很大的空间。
经验公式:每个节点的分片数量保持在低于每1GB堆内存对应集群的分片在20-25之间。分片大小为50GB通常被界定为适用于各种用例的限制。
别名的用法?
- 对于某一个业务设置了每天一个索引,可以给这些索引都加上一个统一的别名。可以合并查询。
- 在代码中设置用别名查询,如果需要更换业务。只需把新业务设置成代码中的别名,同时把就业务的别名删除。这样就无缝切换,不需要该代码重新部署。
- 可以用过滤查询,给查询出来的数据集设置别名,生成一个子集视图。比如过滤查询出电影类型为科幻的类型,给这些数据加别名。以后查询科幻类的电影只需要使用这个别名查询即可。
ES的堆内存怎么设置?
- 官方不建议设置超过32G(超过的话GC影响大)
- 建议:宿主机内存大小的一半和31GB,取最小值。(剩下一般的内存留给Lucene做缓存数据结构)
============== 分割线 ==============
数仓的架构
现在数仓分为三种架构lambda,kappa,OLAP变体
lambda架构
早期的数仓,现在大部分公司都在用吧。就是离线一套,实时一套。需要开发和维护两套代码,成本高。并且两套代码就要占用两份资源,对资源的要求高。
kappa架构
没有离线的部分,用flink或者sparkStreaming实时的ETL,双流join或者和维表join生成小宽表,输出到Hbase,redis,ES,nysql等数据库。
缺点:业务变更时,需要重新编写代码。并且保证消息队列中的消息存放一定的时间。新启动一个任务,从某个历史时间消费消息队列中的数据,直到新任务消费消息的偏移量和旧任务消费齐平的时候。就可以停掉旧任务。旧任务产生的结果表就可以删除。
实时OLAP变体
在kappa架构的基础上,用流处理只是ETL和轻度的聚合,输出到Hbase、hive或者ES,然后用OLAP分析引擎分析(减轻流式处理中聚合的操作),来应对各种分析。
============== 分割线 ==============
Flume
channel数据积压怎么办?
- 增大sink从channel拉取event每批次的大小batchSize
- 增大source到channel的batchSize
- 选择memorychannel来提高效率
- 适当增大transactionCapacity(事务容量),put/take事务的容量。避免频繁的开启事务
Kafka
怎么保证数据的一致性?(不丢不重)
不丢:
生产者设置ack为-1,消费者手动提交偏移量。
不重复:
生产者设置ack-1+开启幂等性+开启事务。消费者可以在下游去重(在hive表中去重)
高频面试题
给两个很大的文件a b,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
假如每个url大小为10bytes,那么可以估计每个文件的大小为50G×64=320G,远远大于内存限制的4G,所以不可能其完全加载到内存中处理,可以采用分治的思想来解决。
- Step1:遍历文件a,对每个url求取hash(url)%1000,然后根据所取得的值将url分别存储到1000个小文件(记为a0,a1,…,a999,每个小文件约300M);
- Step2:遍历文件b,采取和a相同的方式将url分别存储到1000个小文件(记为b0,b1,…,b999);
- 巧妙之处:这样处理后,所有可能相同的url都被保存在对应的小文件(a0vsb0,a1vsb1,…,a999vsb999)中,不对应的小文件不可能有相同的url。然后我们只要求出这个1000对小文件中相同的url即可。
- Step3:求每对小文件ai和bi中相同的url时,可以把ai的url存储到hash_set/hash_map中。然后遍历bi的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。
有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M,要求返回频数最高的100个词
Step1:顺序读文件中,对于每个词x,取hash(x)%5000,然后按照该值存到5000个小文件(记为f0,f1,…,f4999)中,这样每个文件大概是200k左右,如果其中的有的文件超过了1M大小,还可以按照类似的方法继续往下分,直到分解得到的小文件的大小都不超过1M;
Step2:对每个小文件,统计每个文件中出现的词以及相应的频率(可以采用trie树/hash_map等),并取出出现频率最大的100个词(可以用含100个结点的最小堆),并把100词及相应的频率存入文件,这样又得到了5000个文件;
Step3:把这5000个文件进行归并(类似与归并排序);
现有海量日志数据保存在一个超级大的文件中,该文件无法直接读入内存,要求从中提取某天出访问百度次数最多的那个IP
- 从超大文件中逐步读取,根据hash(ip)%1000分别放到1000个内存中可以占下的小文件中
- 对每个小文件进行wordcount,然后找出每个小文件中热度最高的那个词和次数,保存到一个结果文件中
- 然后把1000个文件中的结果加载到内存中,取最大访问次数ip
在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数
方案1:
采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)进行,共需内存2^32*2bit=1GB内存,还可以接受。然后扫描这2.5亿个整数,查看Bitmap中相对应位,如果是00变01,01变10,10保持不变。所描完事后,查看bitmap,把对应位是01的整数输出即可。
方案2:
也可采用与第1题类似的方法,进行划分小文件的方法。然后在小文件中找出不重复的整数,并排序。然后再进行归并,注意去除重复的元素。
腾讯面试题:给40亿个不重复的unsignedint的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
方案1:oo,申请512M的内存,一个bit位代表一个unsignedint值。读入40亿个数,设置相应的bit位,读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在。