原理

Rollover 的原理是使用一个别名指向真正的索引(要求索引的后缀必须是可以递增的数值类型,默认是000001这6位数字),当指向的索引满足一定条件(文档数或时间或索引大小),会新创建一个前缀相同,后缀递增的新索引,并将别名更新到实际指向的索引
image.png :::info 就像上面的图片看到的那样,我们定义了一个叫做 logs-alias 的alias,对于写操作来说,它总是会自动指向最新的可以用于写入index 的一个索引。针对我们上面的情况,它指向 logs-000002。如果新的 rollover 发生后,新的 logs-000003 将被生成,并对于写操作来说,它自动指向最新生产的 logs-000003 索引。而对于读写操作来说,它将同时指向最先的 logs-1,logs-000002 及 logs-000003。在这里我们需要注意的是:在我们最早设定 index 名字时,最后的一个字符必须是数字,比如我们上面显示的 logs-1。否则,自动生产 index 将会失败。 :::

ES Rollover Index API的大致逻辑:

  1. 使用类似xxx-0的格式建立index,注意必须是短横线-+数字结尾。
  2. 建立index时,需要一同添加别名,用来滚动,如xxx-write
  3. 一个专门的线程定时调用Rollover Index API: xxx-write/_rollover,并传入滚动条件以及新index的mappings、settings等。如果满足条件,会自动按传入的参数创建新的index并附加滚动别名如xxx-write,并去掉老的index的滚动别名如xxx-write
  4. 你的写入线程不用停机,只要一直用滚动别名xxx-write来写入就行,不用操心写到哪里了

    例子一: 直接创建

    如果所有数据只存在一个索引下,随着数据积累,索引体积越来越大。为了方便管理ES索引,尽量将数据分散到多个索引里。在ES5.0以后新增了一个rollover API,可以动态的滚动索引。
    满足条件的时候会自动触发,滚动创建新的索引。
    1. PUT /%3Clogs-%7Bnow%2Fd%7D-1%3E
    2. {
    3. "aliases": {
    4. "log_alias": {
    5. "is_write_index": true
    6. }
    7. }
    8. }
    如果大家对于上面的字符串 “%3Clogs-%7Bnow%2Fd%7D-1%3E” 比较陌生的话,可以参考网站 https://www.urlencoder.io/
    实际上它就是字符串 “” 的url编码形式。请注意上面的 is_write_index 必须设置为 true。运行上面的结果是
    1. {
    2. "acknowledged" : true,
    3. "shards_acknowledged" : true,
    4. "index" : "logs-2019.10.21-1"
    5. }

导入数据

  1. POST _reindex
  2. {
  3. "source": {
  4. "index": "kibana_sample_data_logs"
  5. },
  6. "dest": {
  7. "index": "log_alias"
  8. }
  9. }

查看数据

  1. GET logs-2019.10.21-1/_count
  2. {
  3. "count" : 14074,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. }
  10. }

显然,我们已经复制到所有的数据。那么接下来,我们来运行如下的一个指令:

  1. POST /log_alias/_rollover?dry_run
  2. {
  3. "conditions": {
  4. "max_age": "7d",
  5. "max_docs": 14000,
  6. "max_size": "5gb"
  7. }
  8. }

在这里,我们定义了三个条件:

  • 如果时间超过7天,那么自动 rollover,也就是使用新的 index
  • 如果文档的数目超过 14000 个,那么自动 rollover
  • 如果 index 的大小超过 5G,那么自动 rollover

这三个条件是or的关系,有一条满足即触发rollover操作
会把这些数据指向新索引
max_age如果是中午12点创建的index 是从中午还是算的时间24小时为一天, 如”max_age”: “1d”,到隔开中午12点算一天

在上面我们使用了 dry_run 参数,表明就是运行时看看,但不是真正地实施。显示的结果是:

  1. {
  2. "acknowledged" : false,
  3. "shards_acknowledged" : false,
  4. "old_index" : "logs-2019.10.21-1",
  5. "new_index" : "logs-2019.10.21-000002",
  6. "rolled_over" : false,
  7. "dry_run" : true,
  8. "conditions" : {
  9. "[max_docs: 1400]" : true,
  10. "[max_size: 5gb]" : false,
  11. "[max_age: 7d]" : false
  12. }
  13. }

根据目前我们的条件,我们的 logs-2019.10.21-1 文档数已经超过 14000 个了,所以会生产新的索引 logs-2019.10.21-000002。因为我使用了 dry_run,也就是演习,所以显示的 rolled_over 是 false。

为了能真正地 rollover,我们运行如下的命令:

  1. POST /log_alias/_rollover
  2. {
  3. "conditions": {
  4. "max_age": "7d",
  5. "max_docs": 1400,
  6. "max_size": "5gb"
  7. }
  8. }

显示的结果是:

  1. {
  2. "acknowledged" : true,
  3. "shards_acknowledged" : true,
  4. "old_index" : "logs-2019.10.21-1",
  5. "new_index" : "logs-2019.10.21-000002",
  6. "rolled_over" : true,
  7. "dry_run" : false,
  8. "conditions" : {
  9. "[max_docs: 1400]" : true,
  10. "[max_size: 5gb]" : false,
  11. "[max_age: 7d]" : false
  12. }
  13. }

说明它已经 rolled_ovder了。我们可以通过如下写的命令来检查:

  1. GET _cat/indices/logs-2019*

显示结果是
image.png
我们现在可以看到有两个以 logs-2019.10.21 为头的 index,并且第二文档 logs-2019.10.21-000002 文档数为0。如果我们这个时候直接再想 log_alias 写入文档的话:

  1. POST log_alias/_doc
  2. {
  3. "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
  4. "bytes": 6219,
  5. "clientip": "223.87.60.27",
  6. "extension": "deb",
  7. "geo": {
  8. "srcdest": "IN:US",
  9. "src": "IN",
  10. "dest": "US",
  11. "coordinates": {
  12. "lat": 39.41042861,
  13. "lon": -88.8454325
  14. }
  15. },
  16. "host": "artifacts.elastic.co",
  17. "index": "kibana_sample_data_logs",
  18. "ip": "223.87.60.27",
  19. "machine": {
  20. "ram": 8589934592,
  21. "os": "win 8"
  22. },
  23. "memory": null,
  24. "message": """
  25. 223.87.60.27 - - [2018-07-22T00:39:02.912Z] "GET /elasticsearch/elasticsearch-6.3.2.deb_1 HTTP/1.1" 200 6219 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1"
  26. """,
  27. "phpmemory": null,
  28. "referer": "http://twitter.com/success/wendy-lawrence",
  29. "request": "/elasticsearch/elasticsearch-6.3.2.deb",
  30. "response": 200,
  31. "tags": [
  32. "success",
  33. "info"
  34. ],
  35. "timestamp": "2019-10-13T00:39:02.912Z",
  36. "url": "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.deb_1",
  37. "utc_time": "2019-10-13T00:39:02.912Z"
  38. }

显示的结果:

  1. {
  2. "_index" : "logs-2019.10.21-000002",
  3. "_type" : "_doc",
  4. "_id" : "xPyQ7m0BsjOKp1OsjsP8",
  5. "_version" : 1,
  6. "result" : "created",
  7. "_shards" : {
  8. "total" : 1,
  9. "successful" : 1,
  10. "failed" : 0
  11. },
  12. "_seq_no" : 1,
  13. "_primary_term" : 1
  14. }

显然它写入的是 logs-2019.10.21-000002 索引。我们再次查询 log_alias 的总共文档数:

  1. GET log_alias/_count
  2. 显示的结果是:
  3. {
  4. "count" : 14075,
  5. "_shards" : {
  6. "total" : 2,
  7. "successful" : 2,
  8. "skipped" : 0,
  9. "failed" : 0
  10. }
  11. }

显然它和之前的 14074 个文档多增加了一个文档,也就是说 log_alias 是同时指向 logs-2019.10.21-1 及 logs-2019.10.21-000002。

总结:在今天的文档里,我们讲述了如何使用 rollover API 来自动管理我们的 index。利用 rollover API,它可以很方便地帮我们自动根据我们设定的条件帮我们把我们的Index过度到新的 index

例子二: 索引模板

首先创建一个模板方便后续管理 :

PUT /_template/taochy_template
{
  "index_patterns": [
    "taochy-*"
  ],
  "settings": {
      "refresh_interval": "30s",
      "number_of_shards": "1",
      "number_of_replicas": "0"
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      }
    }
  }
}

创建索引:

PUT /taochy-000001
{
  "aliases": {
    "taochy_write_alias": {
      "is_write_index": true
    }
  }
}

设置允许写入写入”is_write_index”:true ,否则无法写入数据,集群只能规定一个写入的索引
插入三条数据:

POST /taochy_write_alias/_bulk?refresh=true
{"name":"aa"}
{"name":"bb"}
{"name":"cc"}

命令返回结果:

{
  "took" : 37,
  "errors" : false,
  "items" : [
    {
      "create" : {
        "_index" : "taochy-000001",
        "_type" : "_doc",
        "_id" : "wVvFttIBUTVfQxRWwXyM",
        "_version" : 1,
        "result" : "created",
        "forced_refresh" : true,
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "create" : {
        "_index" : "taochy-000001",
        "_type" : "_doc",
        "_id" : "wlvFttIBUTVfQxRWwXyM",
        "_version" : 1,
        "result" : "created",
        "forced_refresh" : true,
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "create" : {
        "_index" : "taochy-000001",
        "_type" : "_doc",
        "_id" : "w1vFttIBUTVfQxRWwXyM",
        "_version" : 1,
        "result" : "created",
        "forced_refresh" : true,
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 2,
        "_primary_term" : 1,
        "status" : 201
      }
    }
  ]
}

现在所有的数据都在taochy-000001上,现在执行rollover:

POST /taochy_write_alias/_rollover
{
  "conditions": {
    "max_age":   "1d",
    "max_docs":  3,
    "max_size": "20gb"
  }
}

上述rollover命令指定了三个规则,即时间最长1天 ,数据最多3条,容量最大20GB,这三个条件是or的关系,有一条满足即触发rollover操作
查看执行结果:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "old_index" : "taochy-000001",
  "new_index" : "taochy-000002",
  "rolled_over" : true,
  "dry_run" : false,
  "conditions" : {
    "[max_docs: 3]" : true,
    "[max_size: 20gb]" : false,
    "[max_age: 1d]" : false
  }
}

从上面结果看出来,已经创建了新的索引taochy-000002,原因是最大数据条数已经达到3条了(”[max_docs: 3]” : true),这里还有另外一个操作,就是rollover将别名指向了新生成的taochy-000002了,后续数据会写入taochy-000002中。
再写入一条记录:

POST /taochy_write_alias/_doc
{"name":"dd"}

查看执行结果:

{
  "_index" : "taochy-000002",
  "_type" : "_doc",
  "_id" : "BdbMttIBgpLCCHbxhihi",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

结果符合预期,数据存储在taochy-000002中。