• Redis Plus 来了,性能炸裂!

Redis Plus 来了,性能炸裂!

2025-06-24 08:37:03 栏目:宝塔面板 3 阅读

KeyDB项目是从Redis fork出来的分支。众所周知Redis是一个单线程的kv内存存储系统,而KeyDB在100%兼容Redis API的情况下将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;  //解锁+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处理事件循环中可以再次处理。

Active-Replica

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

  • 每个replica有个uuid标志,用来去除环形复制
  • 新增加rreplay API,将增量命令打包成rreplay命令,带上本地的uuid
  • key,value加上时间戳版本号,作为冲突校验,如果本地有相同的key且时间戳版本号大于同步过来的数据,新写入失败。采用当前时间戳向左移20位,再加上后44位自增的方式来获取key的时间戳版本号。

项目地址:https://github.com/JohnSully/KeyDB

本文地址:https://www.yitenyun.com/301.html

搜索文章

Tags

数据库 API FastAPI Calcite 电商系统 MySQL 数据同步 ACK Web 应用 异步数据库 双主架构 循环复制 Deepseek 宝塔面板 Linux宝塔 Docker 生命周期 JumpServer JumpServer安装 堡垒机安装 Linux安装JumpServer 序列 核心机制 esxi esxi6 root密码不对 无法登录 web无法登录 Windows Windows server net3.5 .NET 安装出错 宝塔面板打不开 宝塔面板无法访问 SSL 堡垒机 跳板机 HTTPS Windows宝塔 Mysql重置密码 连接控制 机制 无法访问宝塔面板 查看硬件 Linux查看硬件 Linux查看CPU Linux查看内存 HTTPS加密 ES 协同 scp Linux的scp怎么用 scp上传 scp下载 scp命令 Serverless 无服务器 语言 日志文件 MIXED 3 修改DNS Centos7如何修改DNS Oracle 处理机制 Spring SQL 动态查询 Rsync RocketMQ 长轮询 配置 Linux 安全 服务器 防火墙 黑客 存储 缓存方案 缓存架构 缓存穿透 MySQL 9.3 HexHub 加密 场景 分页查询 索引 Canal 网络架构 工具 网络配置 聚簇 非聚簇 OB 单机版 开源 PostgreSQL 存储引擎 架构 InnoDB 线上 库存 预扣 技术 ​Redis 机器学习 推荐模型 信息化 智能运维 响应模型 Redis 自定义序列化 数据 业务 人工智能 向量数据库 推荐系统 数据库锁 DBMS 管理系统 B+Tree ID 字段 AI 助手 redo log 重做日志 分库 分表 自动重启 运维 Redis 8.0 Doris SeaTunnel 查询 单点故障 SQLite-Web SQLite 数据库管理工具 GreatSQL Hash 字段 Postgres OTel Iceberg 监控 prometheus Alert 大模型 不宕机 sftp 服务器 参数 共享锁 SQLark Netstat Linux 服务器 端口 微软 SQL Server AI功能 Python Web 容器化 虚拟服务器 虚拟机 内存 崖山 新版本 高可用 优化 万能公式 云原生 Entity 开发 openHalo MVCC SVM Embedding SpringAI • 索引 • 数据库 排行榜 排序 IT运维 分页 数据结构 流量 系统 数据备份 电商 OAuth2 Token PG DBA RDB AOF Testcloud 云端自动化 Redka 缓存 sqlmock 数据集成工具 Ftp EasyExcel MySQL8 同城 双活 MongoDB 容器 PostGIS ZODB 磁盘架构 数据脱敏 加密算法 分布式架构 分布式锁​ 聚簇索引 非聚簇索引 LRU 向量库 Milvus AIOPS StarRocks 数据仓库 Undo Log 主库 网络故障 窗口 函数 数据类型 分布式 集中式 1 池化技术 连接池 引擎 性能 IT dbt 数据转换工具 高效统计 今天这篇文章就跟大家 原子性 mini-redis INCR指令 连接数 Caffeine CP MCP 开放协议 Web 接口 字典 部署 模型 悲观锁 乐观锁 大表 业务场景 管理口 SSH R2DBC InfluxDB RAG HelixDB 对象 发件箱模式 速度 服务器中毒 事务隔离 Redisson 锁芯 JOIN INSERT COMPACT Order 核心架构 订阅机制 单线程 线程 Recursive Pottery 双引擎 QPS 高并发 Go 数据库迁移 网络 分页方案 排版 传统数据库 向量化 启动故障 优化器 LLM 仪表盘 频繁 Codis filelock 工具链 意向锁 记录锁 List 类型 Crash 代码 事务同步 UUIDv7 主键 数据分类 订单 线程安全 Pump 读写 异步化 事务 Java group by 数据页 日志 Ansible R edis