OpenAtomFoundation / pikiwidb

a high-performance, large-capacity, multi-tenant, data-persistent, strong data consistency based on raft, Redis-compatible elastic KV data storage system based on RocksDB
BSD 3-Clause "New" or "Revised" License
202 stars 63 forks source link

feat:Support network read/write separation and command thread pool #164

Closed lqxhub closed 7 months ago

lqxhub commented 9 months ago

fix issue https://github.com/OpenAtomFoundation/pikiwidb/issues/100

加了网络的读写分离,和命令在线程池中执行

这个pr只有 线程池和读写分离功能

后续 还有两个功能, 待开发

cmd_thread_pool 是命令的线程池, 目前支持了快慢命令分离, 但是因现在命令中没有加对应的flag,就暂时全都按照快命令执行了

这是目前我想到的问题


现在的命令线程池中, 所有线程公用了一把锁, 可能会比较重, 如果这部分是瓶颈, 可以和 IO的写线程中那样, 每个写线程 一个独立的队列,然后通过轮训或者别的策略, 向线程池中每个线程的队列加任务,

现在的命令线程池中, 如果慢命令队列是空闲的, 会尝试从 读线程池中偷取 快命令来执行

这段逻辑在

void CmdSlowWorker::LoadWork() {
  {
    std::unique_lock lock(pool_->slowMutex_);
    while (pool_->slowTasks_.empty() && loopMore) {  // loopMore is used to get the fast worker, 定时唤醒去快命令队列中找任务
      pool_->slowCondition_.wait_for(lock, std::chrono::milliseconds(waitTime));
      loopMore = false;
    }

    const auto num = std::min(static_cast<int>(pool_->slowTasks_.size()), onceTask_);
    std::move(pool_->slowTasks_.begin(), pool_->slowTasks_.begin() + num, std::back_inserter(selfTask));
    pool_->slowTasks_.erase(pool_->slowTasks_.begin(), pool_->slowTasks_.begin() + num);
  }

现在还没做对象缓存池, 现在用的做法是 在命令线程池中, 每个线程单独维护一个 cmdTable, 来做命令的隔离

后面设想的是,在读线程中, 解析出 本次命令的参数, 根据第一个参数区分这个命令是 / 命令, 并把所有参数 包装成一个 task 放到对应的线程池中. 在对应的线程池中, 获取这个执行这个命令的对象, 然后执行对应的命令

这样做的考虑是, 在 读线程中就确定命令,并且获取命令的对象, 这样就能做到在向 命令线程池中添加任务时就知道, 当前命令时快命令还是慢命令, 这样就能比较好的做到快慢分离了

每个线程单独维护一个 cmdTable 这个逻辑在

class CmdWorkThreadPoolWorker {
 public:
  explicit CmdWorkThreadPoolWorker(CmdThreadPool *pool, int onceTask, std::string name)
      : pool_(pool), onceTask_(onceTask), name_(std::move(name)) {
    cmd_table_manager_.InitCmdTable();
  }