Elasticsearch使用要点(三)-分布式

分布式文档存储

分片路由:

  • 路由计算公式

    shard = hash(routing) % number_of_primary_shards
    

    这个公式决定了主分片数量在创建以后不可更改.

    但是在后续的水平扩展中可以通过routing路由参数从指定的分片中获取数据.

  • 节点,分片间数据交互参考:官方文档

分页查询:

  • es使用以下两个参数来进行分页

    size:显示应该返回的结果数量, 默认是 10
    from: 显示应该跳过的初始结果数量, 默认是 0
    

    深度分页问题: 当分页深度过大时, 有性能问题. 如from=10000, size=10. 则协调节点向所有的n个分片请求10010个文档数量. 协调节点获取了n 10010个文档后, 排序找到前10个文档再丢弃n 10010 - 10个文档.即在分布式系统中, 对结果排序的成本随分页的深度成指数上升.

    如果你 确实 需要从你的集群取回大量的文档, 你可以通过用 scroll 查询禁用排序使这个取回行为更有效率.

游标查询:

scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询, 而又不用付出深度分页那种代价. (使用场景: 数据导出)

  • 游标查询初始化时会取某个时间点的快照数据, 保存在某个位置.
  • 快照数据可以被指定过期时间.(过期时间会在每次查询时刷新. 故这个时间可以理解为一次请求的最大时间, 后续的连续请求会刷新过期时间. )
  • 初始化后索引上的任何变化会被忽略, 不会再反映到快照数据上.

    1
    2
    3
    4
    5
    6
    GET students/_search?scroll=1m // 指定游标过期时间1分钟
    {
    "query": {"match": {"name": "的"}},
    "sort": [{"id": {"order": "asc"}}], // 排序字段
    "size": 10 // 每批次大小
    }
  • 游标查询返回的结果会有一个_scroll_id字段, 值为base64编码的字符串.

    1
    2
    3
    4
    5
    	GET /_search/scroll
    {
    "scroll": "1m", // 后续请求刷新的游标过期时间
    "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAABVT7FlJSQ3VHeWhhVGlLQ0U5OF9qMGlhWmcAAAAAAAVU4xZ0ME5Uc0hkelFQMkJnZURKdjRxZE5RAAAAAAAFVOYWdDBOVHNIZHpRUDJCZ2VESnY0cWROUQAAAAAABVTlFnQwTlRzSGR6UVAyQmdlREp2NHFkTlEAAAAAAAVU5BZ0ME5Uc0hkelFQMkJnZURKdjRxZE5R"
    }
  • 游标初始化后, 后续的游标查询需指定上次返回的_scroll_id字段, 返回的结果会自动接着上次返回的内容.

映射:

  • Lucene不能存储null字段, 故null值, 空数组, null数组均不会被索引.
  • 字段可以是对象(一个json文档).
  • 内部对象索引后会被打平:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
    "tweet": [elasticsearch, flexible, very],
    "user.id": [@johnsmith],
    "user.gender": [male],
    "user.age": [26],
    "user.name.full": [john, smith],
    "user.name.first": [john],
    "user.name.last": [smith]
    }
  • 内部对象数组也会被打平:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {
    "followers": [
    { "age": 35, "name": "Mary White"},
    { "age": 26, "name": "Alex Jones"},
    { "age": 19, "name": "Lisa Smith"}
    ]
    }

    打平为:

    {
    "followers.age": [19, 26, 35],
    "followers.name": [alex, jones, lisa, smith, mary, white]
    }