你的位置:首页 > 数据库

[数据库]Elasticsearch 搭建集群经验


本文内容

  • 背景
  • ES集群中第一个master节点
  • ES slave节点

本文总结 Elasticsearch(以下简称ES)搭建集群的经验。以 Elasticsearch-rtf-2.2.1 版本为例。

我搭过三个集群:研究ELK时搭了一个;测试环境搭了一个;生产环境搭了一个。回想起来,搭建这三个集群时遇到的问题都不一样(我这么说,主要针对集群中节点发现,以及master问题,而不是es启动不起来或报错等问题)~

  • 研究ELK时,搭建ES集群倒是很顺利,原因很简单,先从一台机器开始的;
  • 可是测试环境搭建集群时,遭遇新加入节点一直不能发现 master 节点,或是集群节点出现都选举自己为 master 这两个情况,因为,节点都是陆续启动的,配置不当,是会出问题;
  • 等到在生产环境搭建集群时,遭遇无法选举出 master 节点的情况。ES head 和 kopf 两个插件都不可用,因为,既然集群没有选举出 master 节点,显然,整个集群是用不了的。而前面的情况,head 和 kopf 插件还是能用的,但能用,意义也不大~

总结起来,搭建集群,应该注意两个问题。首先,当然是 Elasticsearch.yml 配置是否正确;再就是你的操作方式。比如节点启动步骤等。

因为,如果搭建一个集群,那么必须保证集群有一个 master 节点,一般来说,第一个启动的节点,一定是 master。然后,分别启动其他节点,这些节点就会找到 master 节点,而 master 节点,也会发现这些节点。

  • 因此,配置集群中的第一个master节点,务必简单(简单到什么程度,后面再说),先启动它,它会立刻成为 master 节点。之后,再配置其他节点,最好直接告诉它们,可能的 master 节点是什么,然后启动他们,它们就会发现 master,而 master 节点,也会发现新加入的节点。
  • 否则,如果第一个启动的节点,配置过于复杂(条件苛刻),造成它不能成为 master 节点,那么,整个集群会失败。

稍后,你再配置节点时,可以采用更高级、复杂点的配置,就不会有什么问题了~

所以,我才强调,ES 集群中第一个 master 节点的配置务必简单,以后再调整。

背景


假设,我们想搭建这样一个名为 myfirstcluster 的ES集群,它有两个节点:

节点 主机名 是否为 master
192.168.1.2 es-01
192.168.1.3 es-02

ES集群中第一个master节点


最简单的 ES master 节点配置如下。该配置文件,是一个完整的 ES 配置文件,所以很长。我顺便翻译成了中文。

  1: # ======================== Elasticsearch Configuration =========================
  2: #
  3: # 注意: Elasticsearch 大多数设置都有默认值.
  4: #    在你着手调整和优化配置之前,确保你明白你期望什么,得到什么结果
  5: #
  6: # 配置一个节点的主要方式就是通过该文件. 该模板列出了大多数重要的设置.
  7: #
  8: # 更多配置选项参见如下链接:
  9: # <http://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration.html>
 10: #
 11: # ---------------------------------- 集群 -----------------------------------
 12: #
 13: # 集群名称:
 14: #
 15: cluster.name: mycluster
 16: #
 17: # ------------------------------------ 节点 ------------------------------------
 18: #
 19: # 节点名称:
 20: #
 21: node.name: es-01
 22: node.master: true
 23: node.data: true
 24: #
 25: # 为节点添加自定义属性,如机架:
 26: #
 27: # node.rack: r1
 28: #
 29: # ----------------------------------- 路径 ------------------------------------
 30: #
 31: # 存放数据的目录 (多个目录用逗号分隔):
 32: #
 33: # path.data: /path/to/data
 34: #
 35: # 日志文件目录:
 36: #
 37: # path.logs: /path/to/logs
 38: #
 39: # ----------------------------------- 内存 -----------------------------------
 40: #
 41: # 启动时锁定内存:
 42: #
 43: # bootstrap.mlockall: true
 44: #
 45: # 确保设置了 `ES_HEAP_SIZE` 环境变量, 大小为系统内存的一半,
 46: # 该值为线程可以使用的最大内存
 47: #
 48: # 当系统正在交换内存时, Elasticsearch 执行性能会很差.
 49: #
 50: # ---------------------------------- 网络 -----------------------------------
 51: #
 52: # 设置绑定地址到指定IP (IPv4 or IPv6):
 53: #
 54: network.host: 172.16.50.137
 55: #
 56: # 设置自定义 HTTP 端口:
 57: http.port: 9200
 58: # 集群内部通信端口:
 59: transport.tcp.port: 9300
 60: #
 61: # 更多信息, 参见如下链接:
 62: # <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html>
 63: #
 64: # --------------------------------- 节点发现 ----------------------------------
 65: #
 66: # 当新节点加入时,传递一个主机的初始化列表以完成节点发现:
 67: # 默认主机列表为 ["127.0.0.1", "[::1]"]
 68: #
 69: # discovery.zen.ping.unicast.hosts: ["host1", "host2"]
 70: #
 71: # 通过配置大多数节点阻止脑裂现象 (数量: 节点总数量 / 2 + 1):
 72: #
 73: # discovery.zen.minimum_master_nodes: 2
 74: #
 75: # 更多信息, 参见如下链接:
 76: # <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery.html>
 77: #
 78: # ---------------------------------- 网关 -----------------------------------
 79: #
 80: # 当整个集群重新启动后, 只有 N 个节点启动了, 集群才会恢复,否则将阻塞:
 81: #
 82: # gateway.recover_after_nodes: 2
 83: #
 84: # 更多信息, 参见如下链接:
 85: # <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-gateway.html>
 86: #
 87: # ---------------------------------- 其他 -----------------------------------
 88: #
 89: # 禁止在一个系统上启动多个节点:
 90: #
 91: # node.max_local_storage_nodes: 1
 92: #
 93: # 当删除 index 是必需显式名称:
 94: #
 95: # action.destructive_requires_name: true
 96:  
 97: index:
 98:  analysis:
 99:   tokenizer:
 100:    my_pinyin:
 101:     type: pinyin
 102:     first_letter: prefix
 103:     padding_char: ''
 104:    pinyin_first_letter:
 105:     type: pinyin
 106:     first_letter: only
 107:    mmseg_maxword:
 108:     type: mmseg
 109:     seg_type: max_word
 110:    mmseg_complex:
 111:     type: mmseg
 112:     seg_type: complex
 113:    mmseg_simple:
 114:     type: mmseg
 115:     seg_type: simple
 116:    semicolon_spliter:
 117:     type: pattern
 118:     pattern: ";"
 119:    pct_spliter:
 120:     type: pattern
 121:     pattern: "[%]+"
 122:    ngram_1_to_2:
 123:     type: nGram
 124:     min_gram: 1
 125:     max_gram: 2
 126:    ngram_1_to_3:
 127:     type: nGram
 128:     min_gram: 1
 129:     max_gram: 3
 130:   filter:
 131:    ngram_min_3:
 132:     max_gram: 10
 133:     min_gram: 3
 134:     type: nGram
 135:    ngram_min_2:
 136:     max_gram: 10
 137:     min_gram: 2
 138:     type: nGram
 139:    ngram_min_1:
 140:     max_gram: 10
 141:     min_gram: 1
 142:     type: nGram
 143:    min2_length:
 144:     min: 2
 145:     max: 4
 146:     type: length
 147:    min3_length:
 148:     min: 3
 149:     max: 4
 150:     type: length
 151:    pinyin_first_letter:
 152:     type: pinyin
 153:     first_letter: only
 154:   analyzer:
 155:    lowercase_keyword:
 156:     type: custom
 157:     filter:
 158:     - lowercase
 159:     tokenizer: standard
 160:    lowercase_keyword_ngram_min_size1:
 161:     type: custom 
 162:     filter:
 163:     - lowercase 
 164:     - stop
 165:     - trim
 166:     - unique
 167:     tokenizer: nGram
 168:    lowercase_keyword_ngram_min_size2:
 169:     type: custom
 170:     filter:
 171:     - lowercase
 172:     - min2_length
 173:     - stop
 174:     - trim
 175:     - unique
 176:     tokenizer: nGram
 177:    lowercase_keyword_ngram_min_size3:
 178:     type: custom
 179:     filter:
 180:     - lowercase
 181:     - min3_length
 182:     - stop
 183:     - trim
 184:     - unique
 185:     tokenizer: ngram_1_to_3 
 186:    lowercase_keyword_ngram:
 187:     type: custom
 188:     filter:
 189:     - lowercase
 190:     - stop
 191:     - trim
 192:     - unique
 193:     tokenizer: ngram_1_to_3
 194:    lowercase_keyword_without_standard:
 195:     type: custom
 196:     filter:
 197:     - lowercase
 198:     tokenizer: keyword
 199:    lowercase_whitespace:
 200:     type: custom
 201:     filter:
 202:     - lowercase
 203:     tokenizer: whitespace
 204:    ik:
 205:     alias:
 206:     - ik_analyzer
 207:     type: ik
 208:    ik_max_word:
 209:     type: ik
 210:     use_smart: true
 211:    ik_smart:
 212:     type: ik
 213:     use_smart: true
 214:    mmseg:
 215:     alias:
 216:     - mmseg_analyzer
 217:     type: mmseg
 218:    mmseg_maxword:
 219:     type: custom
 220:     filter:
 221:     - lowercase
 222:     tokenizer: mmseg_maxword
 223:    mmseg_complex:
 224:     type: custom
 225:     filter:
 226:     - lowercase
 227:     tokenizer: mmseg_complex
 228:    mmseg_simple:
 229:     type: custom
 230:     filter:
 231:     - lowercase
 232:     tokenizer: mmseg_simple
 233:    comma_spliter:
 234:     type: pattern
 235:     pattern: "[,|\\s]+"
 236:    pct_spliter:
 237:     type: pattern
 238:     pattern: "[%]+"
 239:    custom_snowball_analyzer:
 240:     type: snowball
 241:     language: English
 242:    simple_english_analyzer:
 243:     type: custom
 244:     tokenizer: whitespace
 245:     filter:
 246:     - standard
 247:     - lowercase
 248:     - snowball
 249:    edge_ngram:
 250:     type: custom
 251:     tokenizer: edgeNGram
 252:     filter:
 253:     - lowercase
 254:    pinyin_ngram_analyzer:
 255:     type: custom
 256:     tokenizer: my_pinyin
 257:     filter:
 258:     - lowercase
 259:     - nGram
 260:     - trim
 261:     - unique
 262:    pinyin_first_letter_analyzer:
 263:     type: custom
 264:     tokenizer: pinyin_first_letter
 265:     filter:
 266:     - standard
 267:     - lowercase
 268:    pinyin_first_letter_keyword_analyzer:
 269:     alias:
 270:     - pinyin_first_letter_analyzer_keyword
 271:     type: custom
 272:     tokenizer: keyword
 273:     filter:
 274:     - pinyin_first_letter
 275:     - lowercase
 276:    path_analyzer: #used for tokenize :/something/something/else
 277:     type: custom
 278:     tokenizer: path_hierarchy 
 279:  
 280: #index.analysis.analyzer.default.type: mmseg
 281: index.analysis.analyzer.default.type: ik 
 282:  
 283: # rtf.filter.redis.host: 127.0.0.1
 284: # rtf.filter.redis.port: 6379


说明:

  • 第15行,指定集群名称 myfirstcluster;
  • 第21行,指定节点名称,最好写主机名;
  • 第22和23行,指定该是否可能为master节点,以及是否为数据节点。ES的所说master节点,其实弱化了很多,仅仅就是为了节点发现和选举master节点而已,它甚至都可以不用来保存数据。

因此,看你的规划,完全可以让一个 master 节点,不保存任何数据;

  • 第54行,指定节点IP地址,192.168.1.2;
  • 第57行,指定HTTP端口,比如,head、kopf插件等插件,都使用该端口。事实上,你可以指定从 92开头的任何端口;
  • 第59行,指定集群内部通信的端口,比如,节点发现都使用该端口。事实上,你可以指定93开头的任何端口;

这7行配置,在我看来,针对集群中第一个master节点,必须配置正确的。其他配置,可以暂时不用。

其中,第57行和第59行,实际上,一台物理机,是可以运行多个 ES,只需要指定不同的配置文件即可。

  • 从97行开始,是配置ES的分词。

slave 节点


Slave 节点配置如下。该配置文件内容只列出了配置项,但是是完整的。

  1: # ======================== Elasticsearch Configuration =========================
  2: #
  3: # ---------------------------------- Cluster -----------------------------------
  4: #
  5: # Use a descriptive name for your cluster:
  6: #
  7: cluster.name: myfirstcluster
  8: #
  9: # ------------------------------------ Node ------------------------------------
 10: #
 11: # Use a descriptive name for the node:
 12: #
 13: node.name: es-02
 14: node.master: true
 15: node.data: true
 16: #
 17: # ----------------------------------- Paths ------------------------------------
 18: #
 19: # Path to directory where to store the data (separate multiple locations by comma):
 20: #
 21: # path.data: /path/to/data
 22: #
 23: # Path to log files:
 24: #
 25: # path.logs: /path/to/logs
 26: #
 27: # ----------------------------------- Memory -----------------------------------
 28: #
 29: # ...
 30: #
 31: # ---------------------------------- Network -----------------------------------
 32: #
 33: # Set the bind address to a specific IP (IPv4 or IPv6):
 34: #
 35: network.host: 192.168.1.3
 36: #
 37: # Set a custom port for HTTP:
 38: #
 39: http.port: 9200
 40: transport.tcp.port: 9300
 41: #
 42: # --------------------------------- Discovery ----------------------------------
 43: #
 44: # Pass an initial list of hosts to perform discovery when new node is started:
 45: # The default list of hosts is ["127.0.0.1", "[::1]"]
 46: #
 47: discovery.zen.ping.unicast.hosts: ["192.168.1.2:9300"]
 48: #
 49: # ---------------------------------- Gateway -----------------------------------
 50: #
 51: # ...
 52: #
 53: # ---------------------------------- Various -----------------------------------
 54: # ...
 55:  
 56: index:
 57:  analysis:
 58:   tokenizer:
 59:    my_pinyin:
 60:     type: pinyin
 61:     first_letter: prefix
 62:     padding_char: ''
 63:    pinyin_first_letter:
 64:     type: pinyin
 65:     first_letter: only
 66:    mmseg_maxword:
 67:     type: mmseg
 68:     seg_type: max_word
 69:    mmseg_complex:
 70:     type: mmseg
 71:     seg_type: complex
 72:    mmseg_simple:
 73:     type: mmseg
 74:     seg_type: simple
 75:    semicolon_spliter:
 76:     type: pattern
 77:     pattern: ";"
 78:    pct_spliter:
 79:     type: pattern
 80:     pattern: "[%]+"
 81:    ngram_1_to_2:
 82:     type: nGram
 83:     min_gram: 1
 84:     max_gram: 2
 85:    ngram_1_to_3:
 86:     type: nGram
 87:     min_gram: 1
 88:     max_gram: 3
 89:   filter:
 90:    ngram_min_3:
 91:     max_gram: 10
 92:     min_gram: 3
 93:     type: nGram
 94:    ngram_min_2:
 95:     max_gram: 10
 96:     min_gram: 2
 97:     type: nGram
 98:    ngram_min_1:
 99:     max_gram: 10
 100:     min_gram: 1
 101:     type: nGram
 102:    min2_length:
 103:     min: 2
 104:     max: 4
 105:     type: length
 106:    min3_length:
 107:     min: 3
 108:     max: 4
 109:     type: length
 110:    pinyin_first_letter:
 111:     type: pinyin
 112:     first_letter: only
 113:   analyzer:
 114:    lowercase_keyword:
 115:     type: custom
 116:     filter:
 117:     - lowercase
 118:     tokenizer: standard
 119:    lowercase_keyword_ngram_min_size1:
 120:     type: custom
 121:     filter:
 122:     - lowercase
 123:     - stop
 124:     - trim
 125:     - unique
 126:     tokenizer: nGram
 127:    lowercase_keyword_ngram_min_size2:
 128:     type: custom
 129:     filter:
 130:     - lowercase
 131:     - min2_length
 132:     - stop
 133:     - trim
 134:     - unique
 135:     tokenizer: nGram
 136:    lowercase_keyword_ngram_min_size3:
 137:     type: custom
 138:     filter:
 139:     - lowercase
 140:     - min3_length
 141:     - stop
 142:     - trim
 143:     - unique
 144:     tokenizer: ngram_1_to_3
 145:    lowercase_keyword_ngram:
 146:     type: custom
 147:     filter:
 148:     - lowercase
 149:     - stop
 150:     - trim
 151:     - unique
 152:     tokenizer: ngram_1_to_3
 153:    lowercase_keyword_without_standard:
 154:     type: custom
 155:     filter:
 156:     - lowercase
 157:     tokenizer: keyword
 158:    lowercase_whitespace:
 159:     type: custom
 160:     filter:
 161:     - lowercase
 162:     tokenizer: whitespace
 163:    ik:
 164:     alias:
 165:     - ik_analyzer
 166:     type: ik
 167:    ik_max_word:
 168:     type: ik
 169:     use_smart: false
 170:    ik_smart:
 171:     type: ik
 172:     use_smart: true
 173:    mmseg:
 174:     alias:
 175:     - mmseg_analyzer
 176:     type: mmseg
 177:    mmseg_maxword:
 178:     type: custom
 179:     filter:
 180:     - lowercase
 181:     tokenizer: mmseg_maxword
 182:    mmseg_complex:
 183:     type: custom
 184:     filter:
 185:     - lowercase
 186:     tokenizer: mmseg_complex
 187:    mmseg_simple:
 188:     type: custom
 189:     filter:
 190:     - lowercase
 191:     tokenizer: mmseg_simple
 192:    comma_spliter:
 193:     type: pattern
 194:     pattern: "[,|\\s]+"
 195:    pct_spliter:
 196:     type: pattern
 197:     pattern: "[%]+"
 198:    custom_snowball_analyzer:
 199:     type: snowball
 200:     language: English
 201:    simple_english_analyzer:
 202:     type: custom
 203:     tokenizer: whitespace
 204:     filter:
 205:     - standard
 206:     - lowercase
 207:     - snowball
 208:    edge_ngram:
 209:     type: custom
 210:     tokenizer: edgeNGram
 211:     filter:
 212:     - lowercase
 213:    pinyin_ngram_analyzer:
 214:     type: custom
 215:     tokenizer: my_pinyin
 216:     filter:
 217:     - lowercase
 218:     - nGram
 219:     - trim
 220:     - unique
 221:    pinyin_first_letter_analyzer:
 222:     type: custom
 223:     tokenizer: pinyin_first_letter
 224:     filter:
 225:     - standard
 226:     - lowercase
 227:    pinyin_first_letter_keyword_analyzer:
 228:     alias:
 229:     - pinyin_first_letter_analyzer_keyword
 230:     type: custom
 231:     tokenizer: keyword
 232:     filter:
 233:     - pinyin_first_letter
 234:     - lowercase
 235:    path_analyzer: #used for tokenize :/something/something/else
 236:     type: custom
 237:     tokenizer: path_hierarchy
 238:  
 239: #index.analysis.analyzer.default.type: mmseg
 240: index.analysis.analyzer.default.type: ik


说明:

  • 第7行,也是指定了集群名称;
  • 第13行,指定了节点名称为 es-02(主机名)
  • 第14和15行,指定了该节点可能成为 master 节点,还可以是数据节点;
  • 第35行,指定节点IP地址为 192.168.1.3;
  • 第39行,指定http端口,你使用head、kopf等相关插件使用的端口;
  • 第40行,集群内部通信端口,用于节点发现等;

上面的配置master也是这么配置的。

  • 第47行,跟master节点配置不一样了。这里直接告诉该的节点,可能的master节点是什么。