Solr Sharding将一个Solr的索引分成多个部分,这些被Sharding的索引可能会位于不同的机器上。当数据对于一个节点来说太大时,您可以通过创建一个或多个Shard来分解它,并将其存储在各个section中,每个Shard包含唯一的索引片段。
Shard是collection的一个逻辑分区,它包含了这个collection文档的一个子集,collection中的每个文档只存在一个Shard中。哪个Shard包含collection中的哪个文档则取决于该collection的整体Sharding策略。
举个栗子,我们有一个collection,这个collection的country字段决定了每个文档应该属于哪个Shard。因此,具有相同country的文档将会放置在一起。
不同的collection只是在每个文档的uniqueKey上使用Hash来确定其属于哪个Shard。
Sharding很重要,主要有两个原因:
- 它允许你水平拆分或扩充容量。
- 它允许你跨Shard(可能在多个节点上)分发操作(例如,索引跟踪),从而提高性能/吞吐量。
- 它可以将往Solr中写数据的压力分解到不同的Shard中
在SolrCloud之前,Solr支持分布式搜索(Distributed Search),它允许跨多个Shard执行一个查询。所以,查询是针对整个SOLR索引执行的,这样搜索结果中不会遗漏任何文档。因此,在Shard之间拆分索引并不仅仅是SolrCloud的概念。
Leaders and Replicas
在SolrCloud中没有masters或者slaves。相反,每个shard至少由一个物理replica组成,并且其中必定有一个是Leader。
如果leader挂掉了,其他一个replica将自动当选为新leader。
当文档被发送到Solr节点进行索引时,系统首先确定该文档属于哪个Shard:
+--------------------+
+------>+ Shard1 |
| +--------------------+
|
|
+------------+ |
| Document +------->+
+------------+ |
|
|
| +--------------------+
+------>+ Shard2 |
+--------------------+
然后,确定哪个节点托管了该Shard的Leader。然后,将文档转发给当前的Leader进行索引。
+--------------------+
+-------->+ Replica1 |
| +--------------------+
|
|
+------------+ | +--------------------+
| Shard1 +--------------->+ Replica2 |
+------------+ | +--------------------+
|
|
| +--------------------+
+-------->+ Replica3 Leader |
+--------------------+
然后,Leader会将更新转发给所有其他replica。
+--------------------+
+-------->+ Replica1 +<-------+
| +--------------------+ |
| |
| |
+------------+ | +--------------------+ |
| Shard1 +--------------->+ Replica2 +<-------+
+------------+ | +--------------------+ |
| |
| |
| +--------------------+ |
+-------->+ Replica3 Leader +--------+
+--------------------+
一个Shard至少由一个物理replica组成,多个物理replica有如下优势:
- 它提供了高可用性,如果Shard中的一个replica挂掉了,其它的replica仍可以提供服务。
- 它允许你扩展搜索吞吐量,这是因为搜索可以在所有的replica上并行执行。
Document Routing
Solr通过在创建collection时指定router.name参数,可以指定collection使用的router实现。
Solr中含有两种sharding策略,一种是默认的compositeId(一致性hash),一般在指定numShards参数时会自动切换到router="compositeId"。另一种是implicit。
如果采用compositeId方式,那么就不能动态增加shard。如果采用的是implicit方式,就可以动态的增加shard。
CompositeId
该路由为一致性哈希路由,shards的哈希范围从0~ffffffff。初始创建collection时必须指定numShards。compositeId路由算法根据numShards的个数计算出每个shard的哈希范围,在更新或者新增文档时,根据文档的uniqueKey的hash坐落在那个hash区间来决定这份document数据发送至哪个shard。
0-7fffffff
+--------------------+
+------>+ Shard1 |
| +--------------------+
|
|
+----------------+ document uniqueKey |
| Document +------------------------>+
+----------------+ |
|
| 80000000-ffffffff
| +--------------------+
+------>+ Shard2 |
+--------------------+
使用compositeId路由方式索引可均匀分布在每个shard上。如果你发现你的不同shard之间的数据量差别非常大,那么很可能你的Shard丢失了数据。
Implicit
If you created the collection and defined the "implicit" router at the time of creation, you can additionally define a router.field parameter to use a field from each document to identify a shard where the document belongs. If the field specified is missing in the document, however, the document will be rejected. You could also use the route parameter to name a specific shard.
该路由方式通过定义router.field指定索引具体落在哪个shard,这与compositeId路由方式索引可均匀分布在每个shard上不同,使用Implicit路由方式索引可能不会均匀分布在每个shard上,这依赖于router.field的值分布是否均匀。