Ai
2 Star 0 Fork 3

游建明/java面试相关的问题解答

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
Elasticsearch.java 16.66 KB
一键复制 编辑 原始数据 按行查看 历史
/**
* 描述:Es
* 1.为什么说es是近实时的搜索引擎
* 1.fsync落盘:数据写入es时,通常是先将数据存入虚拟文件系统,也就是内存里,然后调用fsync才能把虚拟文件系统里面的数据落入磁盘。
* 这样做的原因是防止掉电的时候,数据丢失
* 2.segment:elastic是采用lucene这个库来实现倒排索引的,使用segment分段来存储数据,用commit point来记录所有segment的元数据
* 一条数据要被搜索到,必须写入segment中
* 3.translog:es使用translog来记录所有的操作,新增一条记录的时候,es会把数据写到translog和内存缓冲区中
* translog是顺序写的,实时的fsync,性能很高,只要数据写入了translog,就代表落盘了,保证了可靠性
* 每隔5秒钟会把translog刷新(fsync)到磁盘中,也就是说系统掉电的情况下es最多会丢失5秒钟的数据
* 4.内存缓冲区:内存缓冲区和translog是es近实时的关键,因为数据是直接写入到translog落盘的,但是想要数据能被查询到,必须写入segment,
* 需要手动调用refresh操作
* 5.refresh:默认情况下,es每隔一秒钟执行一次refresh,可以通过参数index.refresh_interval来修改这个刷新间隔
* 1.所有内存缓冲区中的文档,写入到一个新的segment中,但是没有调用fsync,数据可能丢失
* 2.segment被打开,使得里面得文档能被搜索到
* 3.清空内存缓冲区
* 6.近实时得原因:内存缓冲区的数据,被写入 segment 文件,且 segment 文件被写入虚拟文件系统后,才能打开这个新 segment 文件,以被检索到。
* 因此在新的segment文件形成前,内存缓冲区里得数据是无法被检索到的。而refresh操作,默认是1s,也就说新插入的数据1s后才能被检索到
* 7.flush:清空translog,虚拟文件系统中的段文件 fsync 刷盘
* 1.把所有在内存缓冲区中的文档写入到一个新的segment中
* 2.清空内存缓冲区
* 3.往磁盘里写入commit point信息
* 4.虚拟文件系统的page cache(segments) fsync到磁盘
* 5.删除旧的translog文件,因此此时内存中的segments已经写入到磁盘中,就不需要translog来保障数据安全了
* 8.flush和fsync的区别:flush是把内存中的数据(包括translog和segments)都刷到磁盘,而fsync只是把translog刷新的磁盘(确保数据不丢失)
* 9.es因为refresh机制,导致近实时的查询,会延迟1s左右;因为translog的机制,如果数据丢失,最多会丢失5s的数据
*
* 2.es核心概念与架构
* 1.索引index:类似mysql的表,一个索引里面存储的是要查询的数据
* 2.类型type:7以前可以定义类型,并且根据类型去查询。7以后就没有类型的概念了
* 3.文档document:一个文档就是一条数据,索引中存储了很多文档,是JSON格式的
* 4.字段Field:相当于表结构的意思
* 5.映射mapping:定义某个字段的数据类型、默认值、分析器、是否被索引等等
* 6.分片shards:一个索引可以存储超过单个节点磁盘大小的数据,或者单个节点处理搜索请求,响应太慢。所以引入了分片机制,
* 将一个索引划分成了多份,每一份称为分片。当创建索引的时候可以指定分片数量,每个分片也是一个功能完善且独立的“索引”
* 1.允许水平分割、扩展存储(有点像redis-cluster结构)
* 2.允许在分片上进行分布式并行的操作,进而提高性能、吞吐量
* 7.副本replices:在一个网络环境中,失败随时可能发生,如果某个分片、节点突然挂了,就需要一个故障转移机制,所以es允许创建副本。
* 一份或多份,创建索引的时候可以设置,副本存储在不同的分片中
* 1.在节点挂了的情况下,提高高可用。复制分片不能跟主分片处于同一台节点中,不然无法保证高可用
* 2.扩展搜索量/吞吐量,因为搜索可以在副本上并行运行(跟redis-cluster不一样,跟redis从节点一样)
* 3.es写入数据流程
* 1.客户端随机选择一个es集群的节点,发送请求,被选择的节点称为协调节点
* 2.协调节点查询集群状态信息并计算路由,将请求发送到真正处理请求的节点(主分片所在的节点)
* 3.包含主分片的节点写入请求,并且将数据同步到包含副本分片的节点
* 1.数据先写入buffer(内存缓冲区)中,在buffer中数据是搜索不到的;同时将数据写入translog日志文件中,保证不丢失
* 2.当buffer达到一定的阈值(如果没数据,不会触发),或者一定时间(默认1s),就会触发refresh,将buffer中的数据写入到一个新的segment中,
* 但是此时这个segment不是磁盘文件,而是先存入os cache。存入后清空buffer。
* 3.数据一写入操作系统缓存,就可以被检索到了。近实时的原因,1s的时差
* 4.文件缓存系统在translog的数据量达到512M或者30分钟时,会触发一次flush,将数据刷入磁盘,然后清除translog
* 4.协调节点收到包含主分片节点的响应信息,将结果返回给客户端
* 4.es读取数据流程
* 1.客户端随机选择es集群中的一个节点,并且发送请求,被选择的节点称为协调节点
* 2.协调节点查询集群状态信息并且使用round-robin算法计算出此次请求的节点,将请求发送到真正处理请求的节点(主分片节点和副本节点随机分配)
* 3.处理读请求的节点将数据返回给协调节点
* 4.协调节点会把文档信息返回给client
* 5.es检索数据的流程(检索是带条件的查询,读取是不带条件的get请求)
* 1.客户端发送请求到一个协调节点
* 2.协调节点将搜索请求转发给所有的分片对应的主分片或者副本分片
* 3.每个分片分片将自己的搜索结果(doc_id),返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果
* 4.接着协调节点,根据doc_id去各个节点上拉取实际的document数据,返回给客户端(注意分页查询,当from特别大的时候会
* 造成大量无用的数据返回给协调节点,谨慎使用)
* 6.es参数优化:
* 1.增加refresh的时间间隔
* 1.为提高索引性能,es写入数据的时候采用延迟写入的策略,数据先写入内存中,当超过默认1s会进行一次refresh,将内存中的segment数据刷新
* 到操作系统中,我们才能搜索数据。
* 2.当我们对数据的时效性要求不高的话,可以将refresh的时间间隔设置长一点或者设置为-1关闭refresh,等数据索引完毕再开启来。
* 3.参数:index.refresh_interval
* 2.减少副本数量
* 1.es7创建索引默认是五个主分片,一个副本,这样会提高集群高可用,提高并发,但是会影响写入效率。因为segment合并的操作在副本分片上也需要进行,
* 2.如果做搜索业务,还是建议副本设置为3个(看节点情况),但是如果是存储日志或者互联网舆情数据,允许数据有一定的丢失,可以只设置1个。
* 3.如果是构建索引插入数据或者reindex的时候,可以先设置为0,后面再恢复预定义的大小
* 3.设置es堆内存,默认是1G,如果节点只部署es,64G内存的话,可以设置成31G,并且确保最小堆内存和最大堆内存相同,防止程序运行时改变堆内存大小。
* 1.为什么不设置的更大:jvm在内存小于32G的时候会采用一个内存对象指针压缩技术,因为这个,其实如果设置的40G也跟32G差不多
* 4.禁止swap:swap是内存和磁盘的交换,影响io和读写速度,,通过bootstrap.memory_lock:true锁定内存。
* 5.修改translog参数,异步更新:
* 1.es为了保证数据不丢失,采用顺序写记录translog文件到磁盘,如果不在意这种丢失,可以设置
* 2.index.translog.durability:async 异步刷写
* 3.index.translog.sync_interval:120s sync时间间隔提高
* 6.修改flush的大小:
* 1.flush的主要目的是把文件缓存系统中的段持久化到磁盘,当translog的数据量达到512M或者30分钟的时候,会触发一次flush
* 2.可以加大,让文件缓存系统存储更多的数据
* 3.index.translog.flush_threshold_size:512M
* 7.磁盘,es是重度使用磁盘,磁盘的吞吐量越大,性能越好,节点越稳定:
* 1.使用SSD
* 2.如果SSD不够(因为比较贵),可以冷热数据分离,热数据,比如最近的数据放SSD,冷数据放普通磁盘
* 8.控制分片数
* 1.分片数的配置,是无法后期修改的,所以需要前期就规划好
* 2.理论上500G的索引,分片数在16个这样,但是还是需要考虑节点的数量
* 3.如果分片数远远大于节点数量,那么就无法保证高可用了,会导致一个节点上存在多个分片,所以一般分片数的设置不超过节点数的三倍
* 7.es查询优化:
* 1.scroll查询:如果要查询大数据量的话,最好避免直接查询,使用scroll翻滚查询,再聚合查询结果
* 2.自动生成id:如果不是业务上的强要求,尽量使用es自己生成id,如果使用特定id,es会检查对应的索引下是否存在相同id,
* 随着文档越来越大,消耗也会越来越大
* 3.少使用nested:创建索引的时候尽量少使用nested类型,并且保证nested类型的字段不能过多,一个document,每一个nested都会生成一个
* 独立的document,影响查询效率,尤其是join的
* 4.批量插入数据使用bulk,bulk默认设置批量提交的数据量不能超过100M
* 8.es选举流程
* 1.Elasticsearch的集群选主是通过ZenDiscovery模块负责的,主要包含Ping(节点之间通过这个RPC来发现彼此)和Unicast(单播模块包含
* 一个主机列表以控制哪些节点需要ping通)这两部分
* 1.ZenDiscory:es自己实现的一套用于节点发现和选主功能的模块
* 2.依赖以下配置发现节点:discovery.zen.ping.unicast.hosts: [1.1.1.1, 1.1.1.2, 1.1.1.3]
* 2.对所有可以成为master的节点(node.master:true)根据nodeId字典排序,每次选举每个节点都把自己知道的所有节点排一次序,
* 然后选出第一个(第0位)节点,暂定它为master节点
* 3.如果对某个节点的投票数达到一定的值(可以成为master节点数 n/2 + 1,节点可以选择自己),那这个节点就是master。
* 否则重新选举一直到满足上述条件
* 4.master节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data节点可以关闭http功能
* 9.es集群脑裂问题
* 1.产生原因
* 1.网络问题:集群间的网络延迟导致一些节点访问不到 master,认为 master 挂掉了从而选举出新的master,并对 master 上的分片和副本标红,
* 分配新的主分片
* 2.节点负载:主节点的角色既为 master 又为 data,访问量较大时可能会导致 ES 停止响应造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,
* 会重新选取主节点
* 3.内存回收:data 节点上的 ES 进程占用的内存较大,引发 JVM 的大规模内存回收,造成 ES 进程失去响应
* 2.解决方案
* 1.减少误判:discovery.zen.ping_timeout节点状态的响应时间,默认3s,如果master在3s内未应答,一般认为是挂了,可以
* 调大参数为 6s,可适当减小误判
* 2.选举触发: discovery.zen.minimum_master_nodes:1。该参数是用于控制选举行为发生的最小集群主节点数量。当备选主节点的个数大于该参数的值
* 且备选主节点中有该参数个节点认为主节点挂了,则进行选举。最好设置成多数原则,比如你有五个候选主节点,设置为(n / 2 + 1),设置为3
* 10.项目中如何使用es的?
* 1.业务:项目中一般存储企业信息,企业变更信息,企业的各类关联数据。或者存储舆情数据,就是互联网爬虫爬取的网络上的头条数据等等
* 2.数据量:看业务吧,企业是近千万家,包含企业的各类变更法人信息等,舆情数据是亿级的,每日入库千万级数据,保留近两个月的数据
* 3.集群大小:不同业务集群也不同,一般是三台集群,内存64G,磁盘单台4T
* 4.优化:企业数据比较侧重于并发读,每日写入不大,但是对数据的可靠性可用性要求高,互联网舆情数据比较侧重于并发写,每日写入量大,但是查询较少,而且允许数据丢失,
* 两种的优化也不一样。
* 1.舆情数据优化,侧重于写入的,一般对集群的一些参数进行优化:
* 1.增加refresh的时间间隔,默认是1s,一般开到30s
* 2.减少副本数量:es默认为1个,有时候不设置副本或者设置1个,看数据,因为丢失了可以再次爬取,但是设置副本占据的数据量太大了,导致磁盘不够用
* 3.设置es的堆内存,64G的机器,设置为31G,而且最大最小堆内存要设置成一样,避免内部加大内存的消耗
* 4.禁止swap:swap是内存和磁盘的交换,要是发生了会导致卡顿,一般设置锁定内存的参数
* 5.修改translog的参数:translog是es防止数据丢失的一种策略,可以设置异步刷新到磁盘,而且可以设置的大一点,flush的时间也可以设置的久一点
* 2.企业数据优化,侧重于读取的,一般是对查询的一些优化,分区和副本数
* 1.设置分区:三台节点的话,分区最大不应该超过节点数的两倍,所以分区设置为6
* 2.设置副本:副本数设置为3,保证并发查询和可用性
* 3.查询优化
* 1.scroll查询:如果要查询大数据量的话,最好避免直接查询,使用scroll翻滚查询,再聚合查询结果
* 1.如果直接使用es的分页,页数越多,会造成大量数据发送到协调节点进行合并和过滤
* 2.自动生成id:如果不是业务上的强要求,尽量使用es自己生成id,如果使用特定id,es会检查对应的索引下是否存在相同id,随着文档越来越大,消耗也会越来越大
* 3.少使用nested:创建索引的时候尽量少使用nested类型,并且保证nested类型的字段不能过多,一个document,每一个nested都会生成一个独立的document,
* 影响查询效率,尤其是join的
* 4.批量插入数据使用bulk,bulk默认设置批量提交的数据量不能超过100M
* 11.es大数据量查询下的优化(数十亿)
* 1.可能产生的问题:搜索的时候,突然来了卡顿,等5-10s才返回,然后后面的查询又快了
* 2.filesystem cache
* 1.es查询数据都是查询文件系统缓存的,会将磁盘中的数据加入到文件系统缓存去,所以需要足够大的filesystem cache
* 2.性能差距是秒级和毫秒级的差距,走纯内存的非常快
* 3.所以如果你仅仅需要查询es的name,age,这两个字段,却把document的另外30个字段都加载进文件系统缓存了,那占据太大空间,就没地方放更多的数据了
* 4.所以一般会将数据存放在hbase中,然后将需要查询的字段放到es中,es查询完了再去hbase中根据id查询,做到毫秒级的响应
* 3.数据预热
* 1.可以用定时任务,将热点数据拿去查询,刷新到文件系统缓存中,加速查询的速度,可以做一个专门的预热子系统
* 4.冷热数据分离
* 1.可以热数据占据一个索引,冷数据一个索引,定期将热数据同步到冷数据中,热数据就用来预热
*
* @author Madison You
* @created 22:27
*/
public class Elasticsearch {
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/you-jianming/code.git
git@gitee.com:you-jianming/code.git
you-jianming
code
java面试相关的问题解答
master

搜索帮助