自适应并发控制协议小组代码协同
1. 负载生成器
统计已有的各种benchmark,发掘表结构和负载普遍的范围区间,按照这个区间比例模拟生成随机负载
2. 负载监视器
需要在各种并发协议,按照相同的硬件配置,各自运行完毕在1中生成的所有负载,并监控负载运行的结果特征。
3. 并发协议训练模型
根据已有的数据训练得出我们需要的模型
项目架构图如下
1. 初始化并发协议
事务具有的基本特征,如长短,读写比等,可以作为我们主要依据的,根据训练模型中得出的数据,我们可以先验性的初始化一个可能最佳的并发控制协议
2. 模型预测
应用模型训练中学习出来的模型,根据当前的监控特征输出我们应该在当前采用的并发控制协议。
3. 切换并发控制协议
在得到最优并发控制协议之后,我们需要将当前的协议切换到下一个并发控制协议。
项目架构图如下
常见的负载特征有如下方面:
-
事务个数(分析TP 总结事务特征)
-
事务的长短,也就是常说的长事务和短事务。这里可以通过调研,给一个比例分布。
-
事务读写比例,这个也可以跟上面一样给一个比例分布;
-
访问分布,这个可以事先定义几种访问分布,如:完全随机的(基本无冲突);低冲突的;高冲突的;秒杀类的。甚至可以用参数(一个连续数值)来控制访问分布,简单点的如:X%的访问落到(1-X%)的数据上。这个X的数值就可以来控制访问分布。
-
负载涉及 数据表数 以及 数据表大小,这个也需要随机产生。
-
分布式事务比例(**是否可以**考虑最基本的hash分库的方式,然后可以用于控制分布式事务比例?)
常见的操作有:
- 读:
-
基于主键过滤 -- 单点; -- 范围(范围有多大,这里需要给一个比例分布~)
-
基于二级索引过滤 -- 单点; -- 范围
-
join
-
写:
同样需要考虑是基于主键的,还是基于二级索引的。以及是单点写,还是范围写(范围大小问题~)。 同时写还需考虑多种操作:insert,update,delete,replace。
由1中获取的负载特征在数据库的不同并发协议上进行模拟。进而可以获得在该并发协议下,负载所表现出来的数据。可描述负载(事务)特征与并发控制协议关联关系的指标有:事务特征值(事务操作数,读写比例等),TPS(QPS),latency,rollback ratio, contention ratio, contention intensity, cache miss ratio, IO per second & bandwidth of Net and Disk,CPU use ratio. CPU context switching ratio, MEM IO and volume, etc。
在特征分布跑出来之后,我们可以拿到一个模型。首先,对于我们每一个构建出来的负载,我们可以得到n(取决于当前需要考虑的并发控制协议个数)个测试结果集。为方便,我们记单个为。之后记每个负载i在并发协议j下的测试结果特征向量为,则共计i*j个特征向量集。
但是难点在于,我们如何根据已有的十几个特征值,来标记最好的并发协议,因此在这里我们需要提出一个计算公式,用来计算当前的选择权重是多少,选择权重越大,则可以认为数据在这个时间段选择此并发协议会相对更好。
<给定一个计算公式>
最终我们的每一条数据的格式,如下:
<concurrency control name> <Feature vectors> <weight>
举个例子:
MVCC 0.1,0.2…,2.7 0.98
因此我们的训练目标是如下问题,根据已有的训练集训练出来的模型,使得我们能够根据此条数据预测该负载在其他n-1个并发控制协议上,理论上的各特征值,然后按照我们给定的公式计算出当前的权重,我们便可以得出最佳的并发控制协议。
在这个地方,我觉得单纯的训练模型不一定可以达到我们需要的效果,一种方法是对每一个并发协议匹配都配置一个模型,如并发协议i到并发协议j的各个特征的映射。那么只需要将特征输入到当前对应的模型中,即可得到理论最佳的并发控制协议,但是这样的话,可扩展性就会变的非常低。或者我们可以将数据的负载特征和当前的并发协议一起用于建模,那么我们只需要建立6个模型。如下图:
但是,在这样一个模型中,我们引入了一个模糊参数,当前协议名称,因此如何选取一个恰当的模型来整合这个参数应该也是比较困难的。
因此如果为了减少训练模型的数量和训练模型的难度,我们可以针对我们的训练目标做如下调整,我们不去做特征的预测,我们预测负载类型,我们为负载分类,即按照负责的固有特征分类,然后我们可以训练目标变为: 获取负载的类型.在这里我们需要考虑的是大部分负载并不是单纯的一种类型,或许是几种类型的混合,因此我们需要得出一个概率分布,即在已经给出的n(需要研究商讨)种负载类型种获取各个范围内的大致分布。 根据负载的概率分布建模,输出应该为最优的并发控制协议。
根据负载的基础特征我们可以拿到一个相对可能会更优的并发控制协议。但是我们如果在去初始化选择的时候,可能没法拿到一定周期的负载数据,因此或许只能制定一个固定的并发控制协议作为开始的协议。
需要优先解决建模的问题。
关于这个问题,我们是否可以实现一个阻拦单元,在切换时阻止新的事务执行,然后当当前事务全部执行完毕之后我们可以更换万并发控制协议,然后执行新的负载。或者我们也可以直接暂停掉当前的数据库?手动切换然后继续运行?