作者:羽洵

来源:http://suo.im/4Cx7u

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

上次也跟大家说了,redis多线程正式版将在今年底发布,大家拭目以待

线程模型

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

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

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

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

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

主线程的主要工作在实现serverCron,包括:

  • 处理统计

  • 客户端链接管理

  • db数据的resize和reshard

  • 处理aof

  • replication主备同步

  • cluster模式下的任务

链接管理

在redis中所有链接管理都是在一个线程中完成的。在KeyDB的设计中,每个worker线程负责一组链接,所有的链接插入到本线程的链接列表中维护。链接的产生、工作、销毁必须在同个线程中。每个链接新增一个字段

int iel; /* the event loop index we're registered with */

用来表示链接属于哪个线程接管。

KeyDB维护了三个关键的数据结构做链接管理:

  • clients_pending_write:线程专属的链表,维护同步给客户链接发送数据的队列

  • clients_pending_asyncwrite:线程专属的链表,维护异步给客户链接发送数据的队列

  • clients_to_close:全局链表,维护需要异步关闭的客户链接

分成同步和异步两个队列,是因为redis有些联动api,比如pub/sub,pub之后需要给sub的客户端发送消息,pub执行的线程和sub的客户端所在线程不是同一个线程,为了处理这种情况,KeyDB将需要给非本线程的客户端发送数据维护在异步队列中。

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

如上文所提到的,一个链接的创建、接收数据、发送数据、释放链接都必须在同个线程执行。异步发送涉及到两个线程之间的交互。KeyDB通过管道在两个线程中传递消息:

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

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

redis有些关闭客户端的请求并非完全是在链接所在的线程执行关闭,所以在这里维护了一个全局的异步关闭链表。

锁机制

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

fastlock的主要数据结构有:

struct ticket
{uint16_t m_active; //解锁+1uint16_t m_avail; //加锁+1
};
struct fastlock
{volatile struct ticket m_ticket;volatile int m_pidOwner; //当前解锁的线程idvolatile 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处理事件循环中可以再次处理。

Active-Replica

KeyDB实现了多活的机制,每个replica可设置成可写非只读,replica之间互相同步数据。主要特性有:

  • 每个replica有个uuid标志,用来去除环形复制

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

  • key,value加上时间戳版本号,作为冲突校验,如果本地有相同的key且时间戳版本号大于同步过来的数据,新写入失败。采用当前时间戳向左移20位,再加上后44位自增的方式来获取key的时间戳版本号。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别!

比Redis快50倍的中间件,为啥这么快?相关推荐

  1. 震惊,使用imba.io框架,得到比 vue 快50倍的性能基准

    上图表示了vue, react 以及 imba 在 todo 这个项目中拥有60个 todoItem 不同进行 crud 操作的表现.可以看到 imba 达到了每秒操作5w次以上.如果你也想试一试该测 ...

  2. C++比Python快50倍?如何让C++和Python优势互补?(Boost::Python)

    目录 1 为什么需要多语言联合编程? 2 Python调用C++的主要方式 2.1 SWIG 2.2 Boost::Python 2.3 ctypes 3 Boost::Python安装 4 测试实例 ...

  3. 论文解读:FastSAM | Fast Segment Anything | 基于yolov8-seg实现 比SAM快50倍

    发表时间:2023.06.21 论文地址:http://export.arxiv.org/pdf/2306.12156 项目地址:https://github.com/CASIA-IVA-Lab/Fa ...

  4. 比Redis快5倍的中间件,为啥这么快?

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"加入公众号专属技术群 来源:http://suo.im/4Cx7u 今天给大家介 ...

  5. 比 Redis 快 5 倍的中间件,KeyDB

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

  6. 比Redis快5倍的中间件,究竟为什么这么快?

    来自:云栖社区 作者:羽洵 原文:https://yq.aliyun.com/articles/705239 今天给大家介绍的是KeyDB,KeyDB项目是从Redis fork出来的分支.众所周知R ...

  7. Batoo JPA –比领先的JPA提供商快15倍

    介绍 我早在2000年代就喜欢JPA 1.0. 我甚至在稳定版本发布之前就将其与EJB 3.0一起使用. 我非常喜欢它,因此我为JBoss 3.x实现贡献了一些零碎的部分. 那时我们公司规模还很小. ...

  8. 掌握这个小技巧,让你的 C++ 编译速度提升 50 倍!

    随着 C++ 项目的持续扩大,编译效率越来越是一个问题了.想一想你每天花在这上面的时间,再乘以团队成员的个数,是不是成本很高? 那有没有什么办法,在不需要修改源码,也不更换硬件的情况下提升效率呢?一起 ...

  9. 【安全资讯】Chrome 的网络钓鱼检测速度提高近 50 倍

    作者|御坂弟弟 来源|开源中国 发布时间|2021-07-21 图片来源:开源中国 在最新发布的 Chrome 92 中,Google 改进了网络钓鱼检测算法,使网络钓鱼检测速度快 50 倍,而电量消 ...

  10. clickhouse大数据分析技术与实战_比Hive快500倍!大数据实时分析领域的黑马

    戳蓝字"小强的进阶之路"关注我们哦! 大数据实时分析领域的黑马是ClickHouse一个用于联机分析(OLAP)的列式数据库管理系统(DBMS). clickhouse背景 俄罗斯 ...

最新文章

  1. 计算机上没有找到服务was,win10系统搭建网站提示计算机“.”上没有找到wAs服务的步骤介绍...
  2. chemdraw怎么画拐弯的箭头_性感皮衣皮裤的质感服装该怎么画?
  3. 循序渐进,学习开发一个RISC-V上的操作系统 5.1答案
  4. [云炬创业基础笔记]第二章创业者测试1
  5. 【oracle】oracle jdbc驱动与c3p0的一个兼容问题
  6. 十条实用的jQuery代码片段
  7. 理论基础 —— 排序
  8. [Grid Layout] Use auto-fill and auto-fit if the number of repeated grid tracks is not to be def
  9. matlab 图像读取长宽_计算机视觉学习笔记1 图像读取显示和尺寸变换
  10. OPPO宣布与哈苏达成影像战略合作
  11. python编程(python开发的三种运行模式)
  12. THREEJS - 动态标签(dom方式)
  13. C语言解决迭代递推问题
  14. 【过拟合】再也不用担心过拟合的问题了
  15. 国企“造船”转行测试,成功拿下11K,如今谁又甘心平庸呢?
  16. 新手程序员如何快速上手公司项目
  17. android 调用webservice实现手机号码归属地查询
  18. 大量数据导出Excel 之 多重影分身之术
  19. SpringBooot
  20. 移动用户远程接入L2TP配置详解

热门文章

  1. 【转】python编写规范——中标软件有限公司测试中心
  2. webpack vs gulp 一张图说明
  3. 读Zepto源码之assets模块
  4. 【原】Eclipse部署Maven web项目到tomcat服务器时,没有将lib下的jar复制过去的解决办法...
  5. 阅读《程序员修炼之道-从小工到专家》阅读笔记02
  6. [Music]乡村摇滚:Any man of mine
  7. 自己编写的新闻显示控件(列表显示不过不够完善还需努力)
  8. inDesign教程,如何将内容与参考线对齐?
  9. 苹果mac pdf编辑器:Acrobat Pro DC
  10. 如何使用 Siri 拨打电话并使用电话功能?