solr mysql splitby_SolrCloud SPLITSHARD原理解析

在本文

首先讲一讲split的好处,当索引达到一定的数量级的时候,搜索的速度或许就会达到一个瓶颈,因为数据量一旦增多,各种查询开销也会一并增加,在solrcloud中,创建索引的时候我们一般都只会创建符合当前性能需求的分片数量,但是数据假如是不可预期的增长的话,那么当当个shard变的很大的时候,我们就可以对这个shard进行拆分,使单个shard中的数据量变少,这也是集群纵向扩展的常用方法。

首先split只支持通过id hash range来区分文档shard的collection,也就是使用ImplicitDocRouter的collection是不能够split的,具体原因后面会说明。

split能够在不影响索引正常提供服务过程中进行,这个是一个亮点,但是索引过大的时候,还是推荐在服务器空闲时进行,因为split会做大量的io读写操作,原因就是索引的分离和复制当然需要读写,而且当原shard有多个复制节点的时候,split也会生成同样多的复制节点,这些节点的数据是需要从leader同步的,索引很大或者replica过多的情况下会耗费大量的网络资源。

具体工作流程:

collectins handler接收命令,确保参数正确后,提交一个队列消息至专门放置collection相关处理消息的分布式队列

这部分是solrcloud的对分布式索引对象操作的基本流程,不详说

overseer collection processor

overseer会启动一个collection processor,用来不停的读取这些消息进行详细的处理,这里就是读到这个消息了,然后开始做split相关操作

clusterState分区处理

这一步其实就是将当前的hash映射范围均等的分为2部分,作为split的两个新的shard的id hash范围。然后创建两个子shard,并且把子shard的状态设置为construction,这里注意的是,假如有两个shard的状态为construction活着inactive,那么会先删掉这两个shard,然后再进行下一步操作,因为这两个shard可能是上一次创建失败留下来的产物。创建好shard后会在原来shard leader所在的那个机器上创建好两个新的core,各个core并且分别加入到新创建好的两个分区shard,对应代码: String subSlice = subSlices.get(i);

String subShardName = subShardNames.get(i);

DocRouter.Range subRange = subRanges.get(i);

log.info("Creating shard " + subShardName + " as part of slice "

+ subSlice + " of collection " + collectionName + " on "

+ nodeName);

Map propMap = new HashMap();

propMap.put(Overseer.QUEUE_OPERATION, "createshard");

propMap.put(ZkStateReader.SHARD_ID_PROP, subSlice);

propMap.put(ZkStateReader.COLLECTION_PROP, collectionName);

propMap.put(ZkStateReader.SHARD_RANGE_PROP, subRange.toString());

propMap.put(ZkStateReader.SHARD_STATE_PROP, Slice.CONSTRUCTION);

propMap.put(ZkStateReader.SHARD_PARENT_PROP, parentSlice.getName());//这里shard多了一个parent属性

ZkNodeProps m = new ZkNodeProps(propMap);

DistributedQueue inQueue = Overseer.getInQueue(zkStateReader.getZkClient());

inQueue.offer(ZkStateReader.toJSON(m));//发消息给overseer队列,overseer读到后会更新clusterstate创建shard

ModifiableSolrParams params = new ModifiableSolrParams();

params.set(CoreAdminParams.ACTION, CoreAdminAction.CREATE.toString());

params.set(CoreAdminParams.NAME, subShardName);

params.set(CoreAdminParams.COLLECTION, collectionName);

params.set(CoreAdminParams.SHARD, subSlice);

addPropertyParams(message, params);

sendShardRequest(nodeName, params);//发送创建replica(core)的消息给对应的节点,这个请求是core admin handler处理的 然后会发消息给两个core节点,等待它们更新自己为active状态,进行下一步数据分割操作。

索引数据分割处理

其实这个才是重头戏的开始,其实也不是什么高深的技术,在solrcloud之前,这个功能就已经存在了,就是core split,collection split就是借这个做了一部分分布式方面的处理,底层还是靠这个,这里要注意的一个核心的方法就是IndexWriter.addIndexes(IndexReader... readers)

OverseerCollectionHandler继续进行处理,发送core split消息给需要分割的core: ModifiableSolrParams params = new ModifiableSolrParams();

params.set(CoreAdminParams.ACTION, CoreAdminAction.SPLIT.toString());//split操作

params.set(CoreAdminParams.CORE, parentShardLeader.getStr("core"));//split源为parent shard,即需要分割的shard

for (int i = 0; i < subShardNames.size(); i++) {

String subShardName = subShardNames.get(i);

params.add(CoreAdminParams.TARGET_CORE, subShardName);//目标源为新分割出来的小shard

}

params.set(CoreAdminParams.RANGES, rangesStr);//同时带上需要分割处理的id hash范围

sendShardRequest(parentShardLeader.getNodeName(), params);//发请求处理 CoreAdminHandler接受到请求后先进行一系列的判断,判断各种条件满足后,提交一个SplitIndexCommand到core的UpdateHandler进行处理,最终还是交给一个叫做SolrIndexSplitter的类来进行分割操作。

SolrIndexSplitter里面需要留意一下的是split方法,这个方法通过从hash range来定位document id将整个reader的docid分割成多个BitSet,有了这个bitset的话,就容易多了。有一个简单的内部类LiveDocsReader,这个类对原来core的所有AtomicReader进行了过滤,让getLiveDocs只返回需要分割出去的的doc,最后调用IndexWriter.addIndexes将数据分割到新的索引中去,IndexWriter.addIndexes所做的就是一个lucene segment merge操作,有了codec,这个操作还是比较方便了。

后期处理

后期处理主要是做一些收尾的操作,比如给各个新的core发送一个提交updatelog的命令,因为刚才在addIndexes操作中,有些数据会缓存在updatelog,这里提交一下。然后就是根据源parent_shard的replica数量给新split出来的shard也创建相同数量的replica,这部分主要就是索引的recovery了,最后发布shard的状态,如果源shard只有一个单节点,即没有replica的话,直接将新的shard发布成active,旧的shard发布成inactive,旧的shard不再接受请求。如果有多个replica需要进行recovery操作的话,新的shard都会被发布成recovery操作,旧shard状态不变,一旦recovery操作完成。overseer自动将新shard发布成active,旧shard发布成inactive。至此,整个shard 的split操作就完成了。还有,inactive状态的shard可以用collection api中的DELETESHARD删除掉,active的shard是不能被删除的。

全文完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值