Elasticsearch 数据写入涉及多个步骤过程,以此来确保数据能够高效、安全地存储在集群中。本文将带你探索 Elasticsearch 对数据的操作流程。
创建索引时,一个 Document 文档需要先经过路由规则定位到主 Shard,发送这个 Doc 到主 Shard 上建索引,成功后在发送这个 Doc 到这个 Shard 的副本上建索引,等副本上建索引成功后才返回成功。
那 Doc 是经过什么样的路由规则定位到 Shard 的呢?下面看一下路由规则。
写入数据,数据应该保存在哪个主分片呢?有个计算叫路由Hash:hash(id) % 主分片数量,对主键进行hash计算,在模主分片数。
写入数据时,在连接集群前是没有路由规则的,集群的信息还不知道。连接时可能连接任意机器,然后经过路由计算,协调节点将数据发送到正确的机器上进行数据写入,主分片写完后,在写入副本分片,然后才给用户返回写入成功。这样会影响性能,可以设置参数来设置数据一致性的程度,如 consistency 参数设置为 one,只要主分片状态 OK 就允许执行写入成功;设置为 all,必须主分片和所有副本分片的状态都没问题才执行成功;设置为 quorum,即大多数的分片副本状态为 OK,即为执行成功,默认为 quorum。
查询数据,不一定从主分片查,还能从副本查询,那查询时如何确定从哪查呢?上图中的分片和副本数量可以保证数据在任何机器上都有,所有查询时查询数据时,查询哪台机器都能查询的到。这叫做分片控制,什么叫分片控制:用户可以访问任何一个节点都能获取数据,这个节点称之为协调节点,这个节点可能会很忙,会把请求转发到另外的节点进行查询。一般的策略是轮询。
在每一个Shard中,写入分为两部分,先写入Lucene,在写入TransLog。
写入请求到达 Shard 后,先写 Lucene 文件,创建好索引,此时索引还在内存里面,接着去写 TransLog,写完 TransLog 后,刷新 TransLog 数据到磁盘上,写磁盘成功后,请求返回给用户。这里有几个关键点,一是和数据库不同,数据库是先写 CommitLog,然后再写内存,而Elasticsearch 是先写内存,最后才写 TransLog,这样的原因:
在创建索引时,应考虑合适的主分片数(primary shards)和副本分片数(replicas)。一旦索引创建完成,其分片数量就不可更改。
Elasticsearch提供了近实时搜索能力,但并非强一致性的系统。对于需要立即反映最新写入状态的应用场景,需要了解其最终一致性的特点。
更新数据时会有并发问题,同一条数据两请求同时更新,那到底以哪个为准呢?
Elasticsearch 采用了乐观锁。Elasticsearch 是分布式的,当文档创建、更新或删除时,新版本的文档必须复制到集群中的其他节点。Elasticsearch 也是异步和并发的。这意味着这些复制请求被并行发送,并且到达目的地时也许顺序是乱序的。Elasticsearch 需要一种方法确保文档的旧版本不会覆盖新版本。
每个文档都有一个 _version(版本号),当文档被修改时版本号递增。Elasticsearch 使用这个version 来确保变更正确的顺序执行。如果旧版本的数据在新版本之后到达,可以被简单的忽略。
Lucene 不支持部分字段的 update,所以需要再 Elasticsearch 中实现该功能,流程如下:
_bulk
API),它能够显著提高性能并减少网络开销。不过要注意批量操作也有其限制,比如单次请求的大小以及系统资源消耗。retry_on_conflict
参数)来处理此类问题。正确理解和运用Elasticsearch的数据更新机制对于保证数据的一致性和系统的稳定性至关重要。同时,针对不同场景采取合适的更新策略和最佳实践,有助于提升集群整体性能。
总之,在Elasticsearch中操作数据时,要熟悉其 RESTful API,合理运用各种查询和更新机制,并根据实际需求采取合适的优化策略。