这次还是以介绍TokuDB内部机制为主, 本篇来谈谈TokuDB内部的线程池模型。
TokuDB内部有一个线程池实现kibbutz, 代码: https://github.com/Tokutek/ft-index/blob/master/util/kibbutz.cc
其调度思想基于work-stealing, 代码也很简洁, 大体思路就是:维护一个任务队列, 空闲线程自己去这个队列领取任务。
kibbutz中文为“基布兹”,是以色列的一个集体社区,感兴趣的戳这里。
TokuDB内部线程池按功能可以分为以下3大块:
节点“饱和”apply线程池
当一个节点“饱和”的时候,TokuDB需要把节点message buffer中的数据apply到子节点(这个行为是由TokuDB的特殊索引结构决定)。
这个线程池的作用是实现并发apply“饱和”节点,线程数目为物理CPU的个数。
缓存专用线程池
这个线程池专门为缓存服务,包括两大块:
a) 节点预读线程,比如做区间查找的时候,在某些条件下会触发子节点预读,提前在后台线程把节点读取到缓存。
b) LRU剔除线程,当缓存大小到达高水位的时候,后台线程把LRU尾端的脏节点刷到磁盘,并从LRU中清除。
这个池子里的线程数目较多,干的活也比较重,线程数目为物理CPU数*2。
checkpoint克隆线程池
这个线程池比较特殊。
做checkpoint的时候,如果一个节点处于“pin”状态,并且它是可克隆的,就使用后台线程把它的数据克隆出来并刷到磁盘,这样checkpoint可以继续进行下去(如果此节点不可克隆,checkpoint线程会一直等到这个pin状态结束)。
这个线程数为物理CPU数/4(如果CPU > 4)。
好的线程池设计+好的任务调度算法,应该是一个引擎高效的最基本条件,让任务尽量并行起来。