batch类批量请求处理流程

Generic表的batch类请求

Generic表的batch类请求包括:
1)batchget请求:批量读请求,对于TDR表,可以设置只返回部分一级字段;对于PB表,不能设置返回部分字段,即只能返回整条记录;
2)batchinsert请求:批量插入请求;
3)batchupdate请求:批量更新请求,如果要更新的记录不存在,则该记录会更新失败;
4)batchreplace请求:批量更新请求,如果要更新的记录不存在,则会插入该记录;
5)batchdelete请求:批量删除请求;
6)batchfieldget请求:批量读请求,只适用于PB表,当用户需要返回PB表的部分字段(包括一级字段和子级字段)时,请使用该请求;

限制


一个batch类请求最多支持对1024条记录进行操作;
一个batch类请求的大小不能超过10MB;

batch类请求处理流程

batch类请求的处理流程主要在接入进程;
1、请求拆分
接入进程接收到batch类请求后,会将batch类请求拆分为一个个单记录的请求发送给存储层:
1)batchget类请求就会拆分为一个个get请求;
2)batchinsert请求会拆分为一个个insert请求;
3)batchupdate请求会拆分为一个个update请求;
4)batchreplace请求会拆分为一个个replace请求;
5)batchdelete请求会拆分为一个个delete请求;
6)batchfieldget请求会拆分为一个个fieldget请求;
2、聚合响应包
接入进程会聚合存储层返回的响应包,并判断是否需要返回客户端响应包:
1)如果达到了分包条件,接入进程会立即返回一个响应包给客户端;
2)如果所有的单记录响应包都返回后,接入进程会返回最后一个响应包给客户端,也标志着该batch类请求处理完成;
3)如果等待单记录响应包超时,那么会按照超时处理流程进行处理;

分包

对于Generic表的batch类请求,默认是开启分包返回的,即接入进程可能会分多个响应包返回给客户端,具体分包策略为:
(1)分包不会切分单条记录,即一个响应包中包含的记录都是完整的,或者说单条记录不会拆分到多个响应包中返回;
(2)当聚合后响应包大小超过256KB时会自动触发分包,即如果聚合后的响应包大小大于256KB时,会立即返回一个响应包给客户端;

batch类读请求记录返回顺序

Generic表的batch类读请求所返回的记录顺序是无序的,比如:
1)batch类请求中记录的顺序为k1, k2, k3, k4,那么返回的响应包中记录的顺序可能为k3,k2,k1,k4,或者k2,k3,k4,k1;
2)对于相同的batch类请求,每次请求所返回的各个响应包中记录的顺序也可能是不一样的;假设batch类请求中记录的顺序为k1,k2,k3,k4,请求了两次,那么这两次对应的响应包中记录的顺序可能为k1,k3,k2,k4 和 k4,k3,k2,k1;

batch类的返回结果

batch类响应包中会包含总错误码以及子错误码,其中,总错误码表示该batch类操作是否成功,子错误码表示每条记录的执行结果;
当总错误码为0时,仅代表整体命令流程没问题, 对每个key,还需有子错误码,代表这条记录执行是否成功。
当总错误码非0时:
1)如果响应包返回的记录数大于0时,那么返回的这些记录都是处理失败的记录,并且可以获取到这些记录的key;
2)如果还有其他未返回的记录,那么那些未返回的记录都是处理失败的记录; 总错误码可以通过response的返回值获取,子错误码通过获取单条记录的返回值得到;

非原子性

batch类的操作不保证原子性,即可能部分成功、部分失败;

超时处理

接入进程对于batch类请求的处理会存在一个超时时间,当前默认为2秒,即2秒内还有单记录响应包没有从存储层返回,那么就认为这些记录超时了,此时接入进程会进行如下处理:
(1)将之前已经聚合但是还未返回给客户端的响应包,发送给客户端;
(2)构造一个新的客户端响应包,响应包的总错误码为超时错误(错误码为-7953),同时还会携带回这些超时记录的key;
(3)将新构建的响应包返回给客户端,同时也标志着这个batch类请求处理完毕; 注:超时时间是可以配置的,如果业务想调整这个超时时间,可以联系DBA进行操作; 另外,这里也提一下sdk侧需要如何判断请求是否超时,这里的超时是指响应包未在业务期望的时间内返回,不同语言的sdk判断方式是不一样的,具体如下:
(1)java sdk跟 C++ pb sdk都是请求超时时自动触发超时回调,业务只需要实现超时回调函数即可;
(2)C++ tdr sdk是要求业务自己实现请求的超时判断逻辑,即业务需要实现相关逻辑来判断请求是否超时;
(3)go sdk是协程,同步接口,超时直接返回一个超时错误码,由用户自己处理; 具体可以参考sdk发布包中的example:

batch类请求与单记录请求性能比较

同样查询1000条记录,从成本角度看,两者几乎没有差异, 因为对存储层的请求模型无差异,而tcaplus的成本主要由存储层决定。
1、对存储层性能的影响
由于batch类请求在接入进程上是拆分为单记录请求发送给存储层的,因此,在操作相同记录数的情况下,batch类请求和单记录请求对存储层性能的影响没有区别;
2、对平均处理时延的影响
由于batch类请求在接入进程上会进行响应包聚合,所以需要等待存储层返回多个响应包之后,才会给客户端回响应包;而单记录请求的响应包在接入进程上不会做额外的处理,会直接返回给客户端,因此,通常情况下,单记录请求的平均处理时延会小于batch类的平均处理时延;
3、对网络流量的影响
由于每个请求和响应都会存在一定的协议开销,因此,在操作相同记录数(记录数大于1)的情况下,batch类请求会比单记录请求节省一定的网络流量;
4、对接入进程cpu的影响
由于batch类请求在接入进程上存在拆分请求和合并响应包的操作,因此,在操作相同记录数的情况下,单记录请求对接入层的cpu开销通常会小于batch类请求;

使用建议


1、如果业务需要等待多条记录响应达到后才能进行操作,那么可以使用batch类请求,也可以使用单记录请求,业务可以根据自身逻辑进行选择;
2、其它情况建议使用单记录请求;

batch类请求使用示例


1、请参考SDK下各个batch类请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/00README.html
2、以C++ TDR表SDK为例:
1)batchget请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/08[Generic表]批量查询多条数据.html
2)batchinsert请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/09[Generic表]批量插入多条数据.html
3)batchupdate请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/10[Generic表]批量更新多条数据.html
4)batchreplace请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/11[Generic表]批量替换多条数据.html
5)batchdelete请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/12[Generic表]批量删除多条数据.html
3、对于batch类请求的响应包,只要响应包中返回的记录数不为0时,那么就可以从响应包中读取记录,不管总错误码是否为0,读取记录后,记录的key一定是有效的,只有当总错误码为0时,记录的value才会有效;

List表的batch类请求

List表的batch类请求包括:
1)listgetbatch请求:批量读请求;
2)listaddafterbatch请求:批量插入请求;
3)listreplacebatch请求:批量更新请求,如果要更新的记录不存在,则该记录会更新失败;
4)listdeletebatch请求:批量删除请求;
请注意,List表的batch类请求都是针对同一个大key下面的多个元素记录进行操作的;

限制


一个batch类请求最多支持对1024条记录进行操作;
一个batch类请求的大小不能超过10MB;

batch类请求处理流程

由于List表的batch类请求都是针对同一个大key下面的多个元素记录进行操作,所以List表的batch类请求会通过接入层直接透传给存储层处理; 存储进程接收到List表的batch类请求后,会在工作线程中一次性处理完请求中涉及的所有记录;比如某个batch类请求中需要对N条记录进行操作,那么工作线程处理时会循环N次,每次处理一条记录; 如果在处理过程中,有记录处理失败时:
1)listaddafterbatch, listreplacebatch, listdeletebatch三类请求,如果某条记录处理失败了,不管是什么原因失败,都会继续处理下一条记录;
2)listgetbatch请求,当读取某条记录失败时,如果失败原因是记录不存在,那么会继续读取下一条记录;如果失败原因不是记录不存在,那么会终止遍历,并返回一个错误响应包给客户端;

分包

PB SDK

对于PB SDK,是默认分包的;

TDR SDK

对于TDR SDK,默认是不分包的,业务需要调用TcaplusServiceRequest::SetMultiResponseFlag()接口设置是否分包:
1)当设置flag=0时,表示不允许分包返回, 这种情况下,只会返回一个响应包;
2)当设置flag=1时,表示允许分包返回,这种情况下,会返回一个或者多个响应包; 正常情况下,业务都应该调用SetMultiResponseFlag()接口设置允许分包返回

分包与不分包的区别


1、对于listgetbatch请求:
1)如果不允许分包返回,那么当读取的记录大小超过一个响应包大小时,会终止后面记录的读取,直接返回响应包给客户端;
2)如果允许分包返回,那么最终会返回要读取的所有记录;
2、对于listaddafterbatch, listreplacebatch, listdeletebatch三类请求:
1)不管是否允许分包返回,都会处理所有的记录,并且响应包都会返回每条记录的处理结果;
2)以listreplacebatch为例,如果设置了需要返回更新之后的记录,当不允许分包时,如果要返回的记录总大小超过一个响应包大小时,超过响应包大小后的记录都不会返回给客户端;当允许分包时,就会将要返回的全部记录都返回给客户端;

分包策略

具体分包策略为:
(1)分包不会切分单条记录,即一个响应包中包含的记录都是完整的,或者说单条记录不会拆分到多个响应包中返回;
(2)当响应包大小超过256KB时,会自动触发分包,并立即返回一个响应包给客户端;

batch类读请求记录返回顺序

List表的batch类读请求所返回的记录顺序是有序的,这里的有序是指:
1)如果业务在插入记录时选择的是尾部插入,那么返回的记录顺序规则为先插入的先返回,比如生成的List index列表为[1,2,3,4,5,6,7,8,9],不管是否存在分包,返回给客户端的记录顺序就是[1,2,3,4,5,6,7,8,9];
2)如果业务在插入记录时选择的是头部插入,那么返回的记录顺序规则为先插入的后返回,比如生成的List index列表为[9,8,7,6,5,4,3,2,1],不管是否存在分包,返回给客户端的记录顺序就是[9,8,7,6,5,4,3,2,1];

batch类的返回结果

batch类响应包中会包含总错误码以及子错误码,其中,总错误码表示该batch类操作是否成功,子错误码表示每条记录的执行结果;
当总错误码为0时,一定会存在子错误码;
当总错误码非0时:
1)如果响应包返回的记录数大于0时,那么通过获取这些记录的返回值得到这些记录的执行结果;
2)如果还有其他未返回的记录,那么那些未返回的记录都是处理失败的记录;
总错误码可以通过response的返回值获取,子错误码通过获取单条记录的返回值得到;

非原子性

batch类的操作都是非原子性的,即不会保证batch类请求中涉及的记录都处理成功或者都处理失败,因此响应包中除了总错误码之外,还会存在子错误码,即每条记录的执行结果;

batch类请求与单记录请求比较


1、对存储层性能的影响
在操作相同记录(记录数大于1)的情况下,对存储层磁盘IO的影响没有区别;但是由于请求和响应都会存在一定的协议开销,所以单记录请求的cpu开销会大于batch类请求的cpu开销; 在操作的记录数为1的情况下,对存储层磁盘IO的影响没有区别;但是由于batch类请求和响应的协议开销大于单记录的协议开销,所以单记录请求的cpu开销会略小于batch类请求的cpu开销;
2、对平均处理时延的影响
由于batch类请求需要处理多条记录之后,才会返回响应包给客户端,因此,通常情况下,单记录请求的平均处理时延会小于batch类的平均处理时延;
3、对网络流量的影响
由于每个请求和响应都会存在一定的协议开销,因此,在操作相同记录数(记录数大于1)的情况下,batch类请求会比单记录请求节省一定的网络流量;如果是操作1条记录,那么单记录请求会比batch类请求节省一定的网络流量;

使用建议


1、如果业务需要对多条记录同时进行操作,那么可以使用batch类请求,也可以使用单记录请求,业务可以根据自身逻辑进行选择;
2、如果是操作单条记录,那么强烈建议使用单记录请求;

batch类请求使用示例


1、请参考SDK下各个batch类请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/00README.html
2、以C++ TDR表SDK为例:
1)listgetbatch请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/24[List表]从列表中批量查询元素.html
2)listaddafterbatch请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/23[List表]向列表中批量插入元素.html
3)listreplacebatch请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/25[List表]向列表中批量更新元素.html
4)listdeletebatch请求的使用说明:https://tcaplusdb.tencent.com/UserGuide/05TcaplusDB_SDK_and_API/01TDR表SDK_and_API/01C++_SDK/02接口文档/26[List表]从列表中批量删除元素.html

批量操作接口的相关说明

批量操作,顾名思议,就是一个请求中可以同时操作多条记录,目前TcaplusDB对于Generic表支持的批量请求包括批量get操作,批量insert操作,批量update操作,批量replace操作,批量delete操作。

  • batch类的操作都是非原子操作,当总的执行结果是成功时,响应包中会给出每条记录的执行结果及错误码;
  • 批量SetKey SetValue注意:批量请求的record在SetKey SetValue之后,调用record的Pack方法打下包(BatchGet和BatchDelete不用调用)

1. 批量操作响应包错误码

批量操作的响应包错误码分为两种:总错误码和子操作错误码。
总错误码表示批量操作的成功与否,子错误码表示单个record的执行结果,只有当总错误码返回成功时,才会存在子错误码;总错误码可以通过response的返回值获取,子操作错误码通过获取单个record的返回值得到。
注意:go sdk,只要有错误就会返回错误,单条的错误码在option里。

2. 批量操作响应包分包

2.1. 分包条件

当响应包超过256KB会触发分包。但保证分包不会切分单个记录(不管这个记录多大),例如,响应包的3个记录分别是10KB、251KB、1MB,会分为2个包返回,即(10KB、251KB)和(1MB)。

2.2. 不同SDK对于分包的行为

  1. 对于PB表 C++ SDK发送的批量操作,TcaplusDB在响应包达到分包条件后,会自动进行分包返回。

  2. 对于TDR表 C++ SDK发送的批量操作,分包规则如下:

    批量get操作,TcaplusDB在响应包达到分包条件后,会自动进行分包返回。

    其他批量操作,可通过TcaplusServiceRequest::SetMultiResponseFlag()接口设置:

    - 当设置flag=0(默认值也是0),表示不允许响应包进行多包返回, 这种情况下,一趟响应若涉及多个记录(超过256KB),只返回第一个响应包(部分记录)。未设置分包,可能会出现返回响应包数据记录为空或者比实际少的情况。
    
    - 当设置flag=1时,表示允许响应包进行多包返回,即允许分包,当TcaplusDB在响应包达到分包条件后,会进行分包返回。
    
  3. 其他SDK,请参考TcaplusDB SDK & API

2.3. 允许分包时,SDK如何判断是最后一个响应包

  1. C++ TDR API,可调用TcaplusServiceResponse::HaveMoreResPkgs()判断;

  2. C++ PB API,回调中返回错误码API_ERR_NO_MORE_RECORD;

  3. 其他SDK,请参考TcaplusDB SDK & API

3. 批量操作响应包是否返回记录

  1. 对于批量get操作,是会返回每条记录的执行结果以及对应的记录数据;

  2. 对于其他批量操作,默认是只返回每条记录的执行结果,而不返回记录数据,如果还需要返回记录数据,SDK可以通过设置一个flag来要求TcaplusDB后台返回记录数据;

  3. batch场景,响应消息必然返回key字段,不会返回value字段(BatchGet除外,会返回value);需要返回value时,请调用request的SetResultFlagForSuccess和SetResultFlagForFail;

4. 批量操作响应包处理

当前以C++ TDR SDK为例,讲解一下批量操作响应包的处理流程:

  1. 先通过response获取响应包的总错误码,如果总错误码不等于0,就表示所有的都处理失败了;总错误码等于0时,表示至少有一条记录处理成功了,可以继续后面的操作;

  2. 调用GetRecordNum()接口来得到当前响应包中携带的记录数,这些记录都是TcaplusDB已经处理过的;BatchGet操作,RecordNum只是查询的key的数量,不是真实结果的记录数;部分key查询partkeyselect,RecordNum部分key返回的记录数,就是响应包中返回的记录数;

  3. 循环调用FetchRecord()接口来获取每条记录的执行结果以及具体的记录数据;当FetchRecord()返回值不为0时,表示这条记录执行失败了;当FetchRecord()返回值为0时,表示这条记录执行成功了,如果设置了返回具体的记录数据,那么可以进一步得到记录数据;

  4. 判断是否是最后一个响应包,如果不是最后一个响应包,那么需要继续接收后续的响应包,如果是最后一个响应包,那么表示此次批量操作已经完成了;

5. 批量操作限制

  1. 一个批量操作最多允许操作1024条记录;

6. BatchGet接口和Get接口,在db后端的查询性能是否有差别?

单个batchget请求与查询相同记录的多个get请求性能差异不会太大,原因在于batchget请求实际上在proxy上会拆分为一个个get请求发送给存储层的,因此,在存储层的性能表现基本上是一致的; 但是gamesvr到proxy之间的流量会有节省,因为每个请求都会有一部分协议头部开销,因此,单个batchget请求相当于节省了一部分协议头部的网络流量开销,同样的,proxy将响应包返回给gamesvr时,由于batchget响应包会一次性返回多条记录,因此,同样也会节省一部分协议头部占用的网络流量; 另外,只有在批量查询的时候才建议使用batchget请求,如果是单条记录查询,强烈建议使用get请求;


各个SDK和API关于批量操作的具体接口和示例,请参考TcaplusDB SDK & API

results matching ""

    No results matching ""