构建合理的ES索引策略
关于索引的大小
由于ES在后续的版本中已经不再支持type,所以建议每一个索引中只存放一个type类型的数据,避免在一个索引中创建多个type。
对于拥有大量数据的索引,我们应该对其进行合理的拆分。由于SaaS服务的特殊性,在SaaS服务中每一个用户都是一个独立的个体,而一个用户的所有的数据都必然是属于该用户的。因此我们选择的策略是根据每个客户的编号来计算其hash值,之后我们在命名ES索引的时候会添加上此hash值。例如对于商品数据,我们可以将索引的名字设置为 products-{hashcode}
,这样的话根据用户编号计算出来的hash值不同将导致用户数据被存储到不同的索引上,如此一来就可以把本来需要保存在一个索引中的数据拆分到多个索引中。具体需要拆分为多少个索引可以根据不同的hash算法来决定,之后在查询数据的时候同样的根据用户编号计算一次hash值就可以得到索引的真实名称,此时只需要去对应的索引中进行数据查找就可以了。
上面这种方式存在两种问题:
- 一旦hash算法确定,之后就不能随意更改。假如我们已经把商品数据拆分到10个独立的索引中了,现在我们发现索引压力依旧较大想要增加索引的数量到20个,但是由于我们的hash算法已经固定所以不能直接添加,因为hash算法一旦改变将导致之前已经存储的数据查询出错,此时只能手动的把数据同步到新的索引中了,相当的麻烦;
- 逻辑上存在关系的数据不应该被拆分到多个索引中,由于我们能够保证一个用户的数据必然被保存在一个指定的索引上,而我们在查询数据的时候必然是根据用户的数据进行查询的,这就使得我们在查询的时候绝对不会出现跨索引查询的情况。如果由于业务上的特点导致无法将数据从逻辑上拆分到多个索引中,这必然会使得在进行数据查询的时候要跨索引,而跨索引的数据查询将必然导致查询操作的复杂化,这是应该被避免的;
索引模板
建议在组建ES集群的时候设置一些合理的索引模板(Index Templates),它的好处在于之后每次创建一个新的索引的时候,都能够给这个索引自动的添加上一些合适的 settings
和 mappings
而不需要手动的去设置这些属性。而且由于索引模板支持通配符,所以我们可以更加细致的针对不同类型的索引来设置不同的配置。
除了Index Templates这个全局的配置,我们在创建索引的时候也可以手动的设置一个索引的mapping,需要注意的是mapping本身包含了 properties
和 dynamic template
这两种配置,前一种是手动的为每一个field设置其mapping,而后一个则是根据ES自动推断出来的此field的类型和field的名称来设置这个field的mapping,所以我们知道了一个field的mapping有三种设置方式:
- 根据mapping中properties来手动设定;
- ES自动的根据field的值来进行动态类型推断而确定一个field的mapping;
- dynamic template可以根据字段被自动推断出来的类型和字段名称来决定一个字段的mapping;
顺便说一下一旦一个字段的mapping被确定了之后就不能被更改了,这也是很容易产生bug的地方。除此之外,我们还应该避免使用动态变化的值作为字段的名称,否则将很容易导致Mapping Explosion。
构建ES集群的策略
把重要且读写量较大的业务数据放到性能更为强劲的ES集群中,将其余的业务数据放到普通的ES集群中,通过这样的策略可以降低ES集群的压力并且提高系统的稳定性。