创造环球焦点网

KeyDB——据说是比Redis快5倍的中间件,为啥这么快? 线程模型 链接管理 锁机制 Active-Replica

  • 日期:2020-01-26 12:51:08
  • 来源:互联网
  • 编辑:小TT
  • 阅读人数:30

KeyDB项目是从redis fork出来的分支。众所周知redis是一个单线程的kv内存存储,而KeyDB在100%兼容redis API的情况下将redis改造成多线程。

线程模型

KeyDB将redis原来的主线程拆分成了主线程和worker线程。每个worker线程都是io线程,负责监听端口,accept请求,读取数据和解析协议。如图所示:

KeyDB——据说是比Redis快5倍的中间件,为啥这么快? 线程模型 链接管理 锁机制 Active-Replica(图1)

KeyDB使用了SO_REUSEPORT特性,多个线程可以绑定监听同个端口。

每个worker线程做了cpu绑核,读取数据也使用了SO_INCOMING_CPU特性,指定cpu接收数据。

解析协议之后每个线程都会去操作内存中的数据,由一把全局锁来控制多线程访问内存数据。

主线程其实也是一个worker线程,包括了worker线程的工作内容,同时也包括只有主线程才可以完成的工作内容。在worker线程数组中下标为0的就是主线程。

主线程的主要工作在实现serverCron,包括:处理统计

db数据的resize和reshard

处理aof

replication主备同步

cluster模式下的任务

int iel; /* the loop index were registered with */

同步发送的逻辑比较简单,都是在本线程中完成,以下图来说明如何同步给客户端发送数据:

KeyDB——据说是比Redis快5倍的中间件,为啥这么快? 线程模型 链接管理 锁机制 Active-Replica(图2)

int fdCmdWrite; //写管道int fdCmdRead; //读管道

本地线程需要异步发送数据时,先检查client是否属于本地线程,非本地线程获取到client专属的线程ID,之后给专属的线程管到发送AE_ASYNC_OP:CreateFileEvent的操作,要求添加写socket事件。专属线程在处理管道时将对应的请求添加到写事件中,如图所示:

KeyDB——据说是比Redis快5倍的中间件,为啥这么快? 线程模型 链接管理 锁机制 Active-Replica(图3)

KeyDB——据说是比Redis快5倍的中间件,为啥这么快? 线程模型 链接管理 锁机制 Active-Replica(图4)

锁机制

KeyDB实现了一套类似spinlock的锁机制,称之为fastlock。

fastlock的主要数据结构有:

struct ticket{ uint16_t m_active; //解锁+1 uint16_t m_avail; //加锁+1};struct fastlock{ volatile struct ticket m_ticket; volatile int m_pidOwner; //当前解锁的线程id volatile int m_depth; //当前线程重复加锁的次数}。

使用原子操作__atomic_load_2,__atomic_fetch_add,__atomic_compare_exchange来通过比较m_active=m_avail判断是否可以获取锁。

fastlock提供了两种获取锁的方式:try_lock:一次获取失败,直接返回

lock:忙等,每1024 * 1024次忙等后使用sched_yield 主动交出cpu,挪到cpu的任务末尾等待执行。

在KeyDB中将try_lock和事件结合起来,来避免忙等的情况发生。每个客户端有一个专属的lock,在读取客户端数据之前会先尝试加锁,如果失败,则退出,因为数据还未读取,所以在下个epoll_wait处理事件循环中可以再次处理。

KeyDB——据说是比Redis快5倍的中间件,为啥这么快? 线程模型 链接管理 锁机制 Active-Replica(图5)

Active-Replica

KeyDB实现了多活的机制,每个replica可设置成可写非只读,replica之间互相同步数据。主要特性有:每个replica有个uuid标志,用来去除环形复制

新增加rreplay API,将增量命令打包成rreplay命令,带上本地的uuid

本文相关词条概念解析:

线程

线程,计算机科学术语,有时也被称为轻量级进程(Light Weight Process,LWP),它是运行中的程序的调度单位。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。线程被包含在进程之中,是进程的一个实体,是CPU调度和分派的基本单位它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

网友评论

提交评论

网站申明:本站图片仅为设计美化,与文章无关。如认为影响您的权益,请与我们联系。