Elasticsearch 中的“近实时”(Near Real-time)全面解析

目录

  • 1. 数据写入与刷新(Refresh)
  • 2. 索引段(Segment)与倒排索引
  • 3. Translog(事务日志)与可靠性
  • 4. 提交点(Commit Point)与数据可见性
  • 5. Flush与数据持久化
  • 6. 近实时搜索的权衡
  • 7. 近实时与实时的区别

Elasticsearch(ES)作为一款流行的分布式搜索引擎,以其近实时(Near Real-Time, NRT)特性著称。这种特性使得ES能够在数据写入后极短的时间内(通常在毫秒至秒级别)使其可被搜索到,虽然不是绝对意义上的实时,但对于大多数应用而言已经足够接近实时,从而满足了对快速响应和数据更新即时可见性的需求。

1. 数据写入与刷新(Refresh)

在ES中,数据写入并不是直接添加到现有的倒排索引中。相反,新数据首先被写入内存缓冲区(In-Memory Buffer),然后定期或按需将缓冲区中的数据合并成一个新的索引段(Index Segment),这个过程称为刷新(Refresh)。默认情况下,ES每秒自动执行一次刷新操作,这意味着大部分情况下,数据写入后最多等待1秒即可被搜索到。用户也可以通过API手动触发刷新,即时使新数据可搜索。

2. 索引段(Segment)与倒排索引

ES底层基于Apache Lucene构建,Lucene使用分段(Segment)的方式来存储数据。每个索引段包含一个独立的、已优化的倒排索引和其他元数据。新写入的数据先被加入内存中的索引段,当刷新发生时,这个内存中的索引段被写入磁盘并打开供搜索使用。由于索引段是独立且不可变的,新数据的添加或现有数据的更新不会影响已存在的索引段,从而避免了对正在被搜索的数据进行锁定或阻塞,保证了搜索的并发性和性能。

3. Translog(事务日志)与可靠性

为了保证数据的可靠性,在数据写入内存缓冲区后,ES还会将其写入事务日志(Transaction Log, Translog)。Translog充当一种持久化记录,即使在系统崩溃或电源故障的情况下,也能确保在重启后通过重放Translog中的操作恢复未刷新到磁盘的最新数据。当一个索引段被刷新并写入磁盘后,对应的Translog条目就可以被清除,释放空间。

4. 提交点(Commit Point)与数据可见性

Lucene使用**提交点(Commit Point)**来跟踪哪些索引段是已知的、安全的,可以用于搜索。每当有新的索引段刷新完成并被认为安全时,就会创建一个新的提交点。搜索请求总是参考最新的提交点,确保只访问已提交的、稳定的索引段,从而提供一致的搜索结果。

5. Flush与数据持久化

除了刷新外,ES还有一个刷新(Flush)过程,它将内存中的所有未刷写到磁盘的索引段强制写入磁盘,并清空Translog。Flush不是为了搜索可见性,而是为了防止Translog过大导致恢复时间过长,以及确保数据在节点故障时不会丢失。默认情况下,ES会根据内存使用情况和Translog大小自动触发Flush。

6. 近实时搜索的权衡

ES的近实时性是通过对数据处理流程进行精心设计和优化实现的,但也存在一些权衡:

  • 延迟与资源消耗:更频繁的刷新会缩短数据变为可搜索的延迟,但也会增加CPU和I/O资源的消耗,可能影响整体性能。用户可以根据实际应用场景调整刷新频率。
  • 数据一致性:在刷新间隔内,新写入的数据可能还未对搜索可见。对于需要严格一致性的场景,可以通过设置适当的刷新策略或使用显式刷新API来最小化这一窗口。
  • 段数量控制:频繁的刷新会导致索引段数量增多,可能影响搜索性能。ES通过段合并(Merge)机制来解决这个问题,将小的、旧的索引段合并成大的、新的索引段,减少段数量并释放空间。

7. 近实时与实时的区别

尽管ES提供了极高的搜索更新速度,但它并不保证数据写入后立即可搜索,这是与“实时搜索”系统的区别所在。实时搜索系统通常要求数据写入后立即对搜索可见,没有明显的延迟。然而,对于大多数应用而言,ES的近实时特性已经足够满足其对时效性的要求,而且提供了更高的可伸缩性和处理大量数据的能力。

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用elasticsearch-dsl可以很方便地将Scrapy爬取的数据存储到Elasticsearch。 首先,需要在Scrapy项目安装elasticsearch-dsl: ``` pip install elasticsearch-dsl ``` 然后,在Scrapy项目的settings.py文件添加以下代码: ``` ELASTICSEARCH_HOST = 'localhost' ELASTICSEARCH_PORT = 9200 ELASTICSEARCH_USERNAME = '' ELASTICSEARCH_PASSWORD = '' ELASTICSEARCH_INDEX = 'my_index' ELASTICSEARCH_TYPE = 'my_type' ``` 这里需要设置Elasticsearch的主机名、端口号、用户名、密码、索引名称和类型名称。 接下来,在Scrapy项目的pipelines.py文件编写以下代码: ``` from elasticsearch_dsl.connections import connections from elasticsearch_dsl import DocType, Text, Date, Integer from scrapy.utils.project import get_project_settings class MyItem(DocType): title = Text() content = Text() publish_date = Date() view_count = Integer() class Meta: index = get_project_settings().get('ELASTICSEARCH_INDEX') doc_type = get_project_settings().get('ELASTICSEARCH_TYPE') class ElasticsearchPipeline(object): def __init__(self): settings = get_project_settings() self.es = connections.create_connection( hosts=[{'host': settings.get('ELASTICSEARCH_HOST'), 'port': settings.get('ELASTICSEARCH_PORT')}], http_auth=(settings.get('ELASTICSEARCH_USERNAME'), settings.get('ELASTICSEARCH_PASSWORD')) ) def process_item(self, item, spider): my_item = MyItem(title=item['title'], content=item['content'], publish_date=item['publish_date'], view_count=item['view_count']) my_item.save(using=self.es) return item ``` 这里定义了一个MyItem类,包含了需要存储到Elasticsearch的字段。ElasticsearchPipeline类则是对数据进行处理和存储的类,其在初始化方法连接Elasticsearch,将数据保存到Elasticsearch的process_item方法则是通过创建MyItem对象并调用save方法来完成的。 最后,在Scrapy项目的settings.py文件添加以下代码启用ElasticsearchPipeline: ``` ITEM_PIPELINES = { 'my_project.pipelines.ElasticsearchPipeline': 300, } ``` 这样,爬取到的数据就会自动存储到Elasticsearch了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值