Partition-Split

功能简介

在pegasus中,表的partition个数是在创建时指定的,并且不会动态改变,但随着数据量不断增大,可能出现partition数据过大的情况,这样可能会导致读写效率下降,因此需要人工增大partition个数来保障服务质量。

在pegasus的设计中,partition个数为2的幂次,目前split功能会将partition个数翻倍,partition(i)将会被分裂为partition(i)和partition(i+original_count) 。例如,原表有4个partition,在split之后将有8个partition,partition(0)将会分裂为partition(0)和partition(4),partition(1)将会分裂为partition(1)和partition(5)……以此类推。我们将partition(i)称为parent partition,partition(i+original_count)称为 child partition

接口描述

partition_split <app_name> <new_partition_count>

  • 若当前表不可用,返回 ERR_APP_NOT_EXIST
  • 若new_partition_count != old_partition_count*2,返回 ERR_INVALID_PARAMETERS
  • 若表正在进行split,返回 ERR_BUSY
  • 若split成功返回 ERR_OK

设计与实现

整体流程

partition split过程可分为以下几个步骤:

  1. client发送partition split请求给meta server。
  2. replica server通过与meta server的config_sync发现表partition个数发生变化。
  3. 每个parent partition通过异步learn的方式复制自己所有数据得到child partition。
  4. 当一个group中的所有child partition就绪后,primary给meta server发送注册child partition的请求。
  5. meta server注册child partition。
  6. 所有child partition被注册完成后,split过程结束。
  7. 清理无效数据,详见如何删除无效数据

Partition-Split过程中的读写

在partition split过程中,读写流程可保持正常进行,在注册child partition期间有短暂拒绝服务。

为了方便说明,假设app的partition个数为4,分裂后为8,而client希望访问的数据,在分裂前由partition(1)服务,分裂后由partition(5)服务。从split开始到partition进行异步learn,都仍将由partition(1)为client进行服务,但当primary给meta server发送注册child partition请求后,partition(1)将拒绝client的读写请求,直到meta server注册完成。当注册完成后,client并不知道将由partition(5)为其服务,仍将请求发送给partition(1),这时partition(1)会提示client更新访问路由表,而更新路由表是对用户透明的。总体来说服务不可用时间非常短。

为什么需要指定partition个数

由于partition split功能不能取消,且没有减小partition的功能,因此执行partition split需谨慎,虽然目前单次split只能使partition个数翻倍,但仍需指定partition count,这是为了防止client多次重试这个非幂等操作导致partition个数非预期增大。

如何删除无效数据

执行partition split前需要保证磁盘空间可用超过50%,内存可用充足,因为split操作首先需要对每个partition进行复制,在split完成后,pegasus会通过rocksdb提供的filter功能在后台删除split造成的无效数据。若磁盘资源紧张或者希望尽快删除无效数据,可在集群CPU空闲期间执行manual_compact功能,手动触发filter,命令详情参见操作示例

Partition-Split与热点问题

split功能主要是为了保障在数据量非预期增长情况下的服务质量,并不能完全解决单个partition过热的问题,pegasus的数据模式是hash分片,在split完成后流量并不能保障是被平分在两个partition上,这个是依赖于用户的hashkey决定的,只能说可以缓解热点问题,并且partition split是表级命令,暂时不支持针对单个partition的partition split。

操作示例

执行Partition-Split

在split前,建议先通过app_stat命令查看待split表的大小,再执行如下命令:

>>> partition_split split_table 8
split app split_table succeed

通过shell工具执行partition split,将split_table partition count从4设置为8

Partition-Split过程中

>>> app split_table -d
[Parameters]
app_name: split_table
detailed: true

[Result]
app_name          : split_table
app_id            : 2
partition_count   : 8
max_replica_count : 3
details           :
pidx      ballot    replica_count       primary                                 secondaries                             
0         3         3/3                 10.239.35.234:34802                     [10.239.35.234:34803,10.239.35.234:34801]
1         3         3/3                 10.239.35.234:34803                     [10.239.35.234:34801,10.239.35.234:34802]
2         3         3/3                 10.239.35.234:34801                     [10.239.35.234:34803,10.239.35.234:34802]
3         3         3/3                 10.239.35.234:34802                     [10.239.35.234:34801,10.239.35.234:34803]
4         -1        0/0                 -                                       []
5         -1        0/0                 -                                       []
6         -1        0/0                 -                                       []
7         -1        0/0                 -                                       []

node                                    primary   secondary total     
10.239.35.234:34801                     1         3         4         
10.239.35.234:34802                     2         2         4         
10.239.35.234:34803                     1         3         4         
                                        4         8         12        

fully_healthy_partition_count   : 4
unhealthy_partition_count       : 4
write_unhealthy_partition_count : 4
read_unhealthy_partition_count  : 4

list app split_table succeed

通过app <table_name> -d命令查看当前表的详情,ballot=-1表示该partition还没有被meta server注册

Partition-Split完成

同样通过app <table_name> -d查看表详情,当发现所有ballot都大于0时表示所有partition都被注册,若当前流量不大可以将meta server设置为lively状态,进行负载均衡,并且通过app_stat命令查看表的大小,应该是split前的2倍左右

手动触发Manual-Compact

关于Manual compact详情可参见Manual compact功能,在集群CPU空闲时进行操作,建议命令示例如下: ./scripts/pegasus_manual_compact.sh -c <meta_list> -a <table_name>

Copyright © 2023 The Apache Software Foundation. Licensed under the Apache License, Version 2.0.

Apache Pegasus is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.

Apache Pegasus, Pegasus, Apache, the Apache feather logo, and the Apache Pegasus project logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.