数据库修仙元婴篇二——dcf写入机制

数据库修仙元婴篇三——一文读懂openguass dcf网络模块 一文读懂openguass dcf网络模块 阅读详情

dcf写入机制

写入

dcf提供如下两个写入接口:

  • dcf_write

    int dcf_write(unsigned int stream_id, const char* buffer, unsigned int length, unsigned long long key, unsigned long long *index);
    

    仅在leader节点调用。

  • dcf_universal_write

    int dcf_universal_write(unsigned int stream_id, const char* buffer, unsigned int length, unsigned long long key, unsigned long long *index);
    

    可以在任意节点调用。

确认

  • dcf_register_after_writer

    用于注册leader节点写入成功回调函数。

    int dcf_register_after_writer(usr_cb_after_writer_t cb_func)
    {
        return rep_register_after_writer(ENTRY_TYPE_LOG, cb_func);
    }
    

    最终将回调函数注册到全局变量

    int rep_register_after_writer(entry_type_t type, usr_cb_after_writer_t cb_func)
    {
        g_cb_after_writer[type] = cb_func;
        return CM_SUCCESS;
    }
    

    调用流程如下:

启动个线程来执行apply
rep_common_init
cm_create_thread
rep_apply_thread_entry
rep_apply_proc
g_cb_after_writer

线程在等待条件变量释放,并执行apply。

// 先查出有多少条流
if (md_get_stream_list(streams, &stream_count) != CM_SUCCESS) {
        LOG_DEBUG_ERR("[REP]md_get_stream_list failed");
        return;
    }
while (!thread->closed) { // 若线程没有关闭则循环等待
        if (!exists_log) { // 首先判断是否存在日志,不存在就休眠等待唤醒
            (void)cm_event_timedwait(&g_apply_cond, CM_SLEEP_500_FIXED);
        }
        LOG_TRACE(g_rep_tracekey, "apply_thread work");
        exists_log = CM_FALSE;
        for (uint32 i = 0; i < stream_count; i++) { // 遍历每一条流
            uint32 stream_id = streams[i];
            bool8 stream_exists_log = CM_FALSE;
            LOG_TIME_BEGIN(rep_apply_proc);
            // 执行apply
            if (rep_apply_proc(stream_id, &stream_exists_log) != CM_SUCCESS) {
                LOG_DEBUG_ERR_EX("[REP]rep_apply_proc failed.");
            }
            LOG_TIME_END(rep_apply_proc);

            exists_log = (exists_log || stream_exists_log);
        }
    }

其中等待的条件变量为,在如下的地方唤醒。

void rep_apply_trigger()
{
  LOG_DEBUG_INF("[REP]rep_apply_trigger");
  LOG_TRACE(g_rep_tracekey, "common:rep_apply_trigger.");
  cm_event_notify(&g_apply_cond);
}

rep_apply_trigger的调用栈如下;

leader
follower
rep_acceptlog_proc
rep_leader_acceptlog_proc
rep_try_commit_log
rep_apply_trigger
rep_accept_thread_entry
rep_follower_acceptlog_proc

经过上面调用流程可以看到,apply线程是由accept线程唤醒的。accept线程与apply线程类似,同样是等待条件变量将线程唤醒。

if (md_get_stream_list(streams, &stream_count) != CM_SUCCESS) {
        LOG_DEBUG_ERR("[REP]md_get_stream_list failed");
        return;
    }

    while (!thread->closed) {
        if (!exists_log) {
            LOG_TRACE(g_rep_tracekey, "accept_thread wait.");
            (void)cm_event_timedwait(&g_accept_cond, CM_SLEEP_500_FIXED);
        }
        LOG_TRACE(g_rep_tracekey, "accept_thread work.");

        exists_log = CM_FALSE;
        for (uint32 i = 0; i < stream_count; i++) {
            uint32 stream_id = streams[i];
            date_t now = g_timer()->now;
            exists_log = (exists_log || g_common_state[stream_id].accept_log);
            if (g_common_state[stream_id].accept_log ||
                now - g_common_state[stream_id].last_accept_time > CM_DEFAULT_HB_INTERVAL*MICROSECS_PER_MILLISEC) {
                LOG_TRACE(g_rep_tracekey, "accept_thread do work.");
                g_common_state[stream_id].accept_log = CM_FALSE;
                g_common_state[stream_id].last_accept_time = now;
                if (rep_acceptlog_proc(stream_id) != CM_SUCCESS) {
                    LOG_DEBUG_ERR("[REP]rep_acceptlog_proc failed.");
                }
            } else {
                LOG_TRACE(g_rep_tracekey, "accept_thread no work.");
            }
        }
    }

accept线程等待的条件变量为g_accept_cond,其唤醒流程如下:

void rep_set_accept_flag(uint32 stream_id)
{
    LOG_DEBUG_INF("rep_set_accept_flag.");
    g_common_state[stream_id].accept_log = CM_TRUE;
    cm_event_notify(&g_accept_cond);
}

rep_set_accept_flag调用堆栈如下:

stg_register_cb
rep_accepted_trigger

可以看已看到accept线程的唤醒是通过注册回调函数来触发的。

    if (stg_register_cb(ENTRY_TYPE_LOG, rep_accepted_trigger) != CM_SUCCESS) {
        LOG_DEBUG_ERR("[REP]rep register stg callback failed");
        return CM_ERROR;
    }
status_t stg_register_cb(entry_type_t type, void *func)
{
    switch (type) {
        case ENTRY_TYPE_CONF:
            g_write_conf_func = (write_conf_func_t)func;
            break;
        case ENTRY_TYPE_LOG:
            g_notify_rep_func = (notify_rep_func_t)func;
            break;
        default:
            LOG_RUN_ERR("[STG]Register callback failed");
            return CM_ERROR;
    }
    return CM_SUCCESS;
}

可以看到回调函数最终被注册到了g_notify_rep_func。

append线程
disk_thread_entry
process_append_action
stream_append_entry_impl
callback_rep_func
g_notify_rep_func
stream_batcher_flush

可以看到其中一个回调函数是由append线程触发的,append线程会等待stream->disk_event条件变量被唤醒。stream->disk_event在stream_append_entry中被唤醒。

rep_appendlog_req_proc
rep_follower_process
rep_follower_appendlog
stg_append_entry
stream_append_entry
rep_write
register_msg_process(MEC_CMD_APPEND_LOG_RPC_REQ, rep_appendlog_req_proc, PRIV_LOW);

MEC_CMD_APPEND_LOG_RPC_REQ在rep_appendlog_node中发送。

rep_appendlog_thread_entry
rep_appendlog_stream
rep_appendlog_node

rep_appendlog_thread_entry有条件变量g_appendlog_cond唤醒。g_appendlog_cond又通过rep_appendlog_trigger唤醒。

rep_write
rep_appendlog_trigger
rep_appendlog_ack_proc
rep_rematch_proc

rep_appendlog_trigger由MEC_CMD_APPEND_LOG_RPC_ACK消息触发。

register_msg_process(MEC_CMD_APPEND_LOG_RPC_ACK, rep_appendlog_ack_proc, PRIV_LOW);

dd

  • dcf_register_consensus_notify

    用于注册follower节点写入数据成功的回调函数。

深入大模型-52-Harness综述之(二)四大子系统 一个Harness都由四个子系统拼成,Agentic Loop是主干,四个子系统是Tool系统、Memory & Context、Guardrails,再加上一个把它们优雅组织起来的Skill系统。 阅读详情

相关推荐

车载机器人终极解决方案:从功能叠加到生态融合的颠覆性变革

本文提出一种融合智能汽车与家居技术的车载机器人架构。其创新点包括:1)基于多模态传感器的拟人化硬件设计,实现声源定位误差<5°、体温检测精度±0.3℃;2)跨模态情感计算引擎,综合面部表情、心率等数据构建三维情绪模型;3)协议自适应中间件,支持小米、华为等多品牌智能家居设备即插即用;4)环境自适应舵机控制,-30℃环境下扭矩保持率达92.5%。测试数据显示,该方案使交互步骤减少60%,用户满意度提升58%,日均使用时长增加2.3倍,为"人-车-家"生态融合提供了可行技术路径。

qq_42671193的博客 1130

数据库修仙元婴篇一——dcf配置解析机制(元数据)

dcf配置解析机制(元数据)

growdu的网络博客 1069

从零实现机械臂抓取仿真:用MoveIt+Gazebo完成物体pick&place全流程

本文详细介绍了如何使用ROS的MoveIt框架与Gazebo仿真环境,从零构建机械臂抓取仿真系统。涵盖环境搭建、MoveIt配置、Gazebo集成、抓取动作实现等全流程,帮助开发者掌握机械臂控制的核心技术,实现高效的pick&place任务。

weixin_29250403的博客 477

循环嵌套(多层 for 循环)

表:order(订单表,order_id, user_id)、user(用户表,user_id, user_name)✅ 优化:先查所有订单,拿到所有 user_id 批量 in 查询,内存 join。✅ 优化:先把优惠券转 HashMap,单层循环查找(hash 查找 O (1))SQL 只有 2 次,O (1) 数据库查询,内存遍历 O (n)。需求:查询所有订单列表,同时带出每个订单对应的用户名称。需求:订单列表、优惠券列表,把订单匹配对应的优惠券名称。复杂度:O (M+N),非常快。

weixin_43732943的博客 191

ADSP-21565的SigmaStudio图形化编程实战:从FW工程改造到音频通道打通

本文详细介绍了如何将ADSP-21569的SigmaStudio图形化编程固件工程改造,以适配ADSP-21565的纯片内SRAM内存架构。通过修改内存映射和链接文件,打通了音频输出通道,并成功利用SigmaStudio进行图形化编程,实现了从白噪声生成到音频输出的完整验证流程。

weixin_29169505的博客 381

从零构建高精度温控系统:ADN8835的单电感拓扑与0.01℃稳定性实战解析

本文深入解析了如何利用ADN8835构建高精度温控系统,重点介绍了其创新的单电感拓扑架构如何实现0.01℃的长期稳定性。内容涵盖精密PCB布局、电源滤波设计,并详细阐述了针对不同热容负载的数字PID控制参数整定策略,为开发精密仪器和医疗设备提供了实战指南。

r2s3t4的博客 240

Python+Agent入门笔记(六):记忆和状态,从“一次性问答”到“能用助手”

滑动窗口的缺点很明显:被扔掉的信息就真没了。如果用户第一轮说“我不吃辣”,隔了二十轮让他推荐餐厅,模型已经忘了。定期把旧的对话压缩成一段总结,作为一条特殊的消息插进去。"""把除 system 和最近 keep_recent 条以外的消息,压缩成一条摘要。返回新的 messages 列表。"""# 把旧消息拼成纯文本,让模型总结content = f"[工具结果]把除 system 和最近 keep_recent 条以外的消息,压缩成一条摘要。返回新的 messages 列表。

qq_41241612的博客 103

RAP 语义键:让 UUID 世界变得可读、可导航、可校验

RAP 语义键的核心价值与实现要点 语义键(Semantic Key)是 ABAP RAP 模型中连接技术实现与业务体验的关键设计:通过为实体指定一组业务可读的标识字段(如订单号、物料编码等),在保持技术主键(如UUID)不变的同时,显著提升用户界面的可读性和导航体验。 主要优势: 提升UI可读性:Fiori元素会突出显示语义键字段,帮助用户快速识别关键业务数据 改善导航体验:OData URL会使用可读的语义键而非技术ID,便于分享和排查问题 降低沟通成本:业务人员能准确引用有意义的业务标识而非技术ID

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 156

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

a bit 205

大数据分析案例-基于决策树算法构建信用卡违约预测模型

本项目旨在使用机器学习等算法构建信用卡违约预测模型,主要应用在金融相关领域,根据用户以往的行为数据来预测是否会违约,有利于商业银行防范和化解信用卡风险,完善信用卡违约风险管理工作。本次实验通过探索性分析以及使用决策树构建信用卡违约模型,得出以下结论:1.可透支金额主要集中在0~200000之间。2.性别对于可透支金额的影响较小。3.受教育程度和婚姻状况对可透支金额的影响较大。4.决策树模型的准确率为0.88,模型效果还有待提高。

m0_64336780的博客 7575

rk3588平台USB 3.0 -OAK深度相机适配方法

摘要:本文记录了OAK摄像头设备的配置与测试流程。主要内容包括:1)添加USB设备udev规则;2)拉取相关依赖库;3)安装Python3和pip;4)安装项目依赖;5)安装FFmpeg工具;6)测试摄像头功能并转换视频格式;7)将测试视频拷贝到U盘查看。操作步骤涵盖了从设备驱动配置到功能测试的完整流程,提供了详细的命令行操作指引。通过该文档可快速完成OAK摄像头的环境搭建和基础功能验证。

yy_hear的博客 325

C# 数据结构和特殊类型

.NET Core(现称.NET)提供丰富数据结构,优化性能与开发效率。日常开发首选List<T>和Dictionary<TKey,TValue>;高性能场景推荐Span<T>与Memory<T>减少内存分配;并发环境使用ConcurrentDictionary等线程安全集合;避免非泛型集合如ArrayList。

cccloveforever的博客 708

数字逻辑Fundamentals of Digital Logic with Verilog Design | 3rd Edition Solutins Chapter 2(step by step)

数字逻辑第二章习题和详细步骤 2-1 ~ 2-78

weixin_62651190的博客 2308

C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?

第17课:用大白话讲清 list 的双向链表结构、哨兵头、push_back 四步、迭代器封装、merge 与 splice 的区别,以及 vector 排序为什么常比 list 快。

wo_jack的博客 242

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

工厂设备接MES为什么慢:协议识别与点表配置自动化的技术拆解

工业现场设备接 MES 的周期主要消耗在协议识别与点表配置。本文拆解这条链路的四层结构,给出点表映射的数据模型、两种部署架构的对比,以及可直接落地的三项验收口径与校验代码。适合工控集成、MES 实施、设备联网方向的工程师。

emfuture的博客 402

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

list

的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。迭代到该位置,在这段位置上迭代需要线性的时间开销;最大的缺陷是不支持任意位置的随机访问,比如:要访问。还需要一些额外的空间,以保存每个节点的相关联信息。个元素,必须从已知的位置。

xie0510_的博客 287

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

软件商店常见问题标准处理流程

从底层软件源来看,/etc/apt/sources.list配置错误、源地址失效、公网与内网离线源混用、ARM64与x86_64架构源串用,以及DNS解析异常、系统代理配置错误,都会导致商店无法获取应用数据;打开该应用,确认可正常运行;软件商店作为系统内置的图形化软件分发与安装入口(UKUI桌面配套组件,底层依赖APT软件源),承担着应用软件的浏览、搜索、下载、安装、升级与卸载等核心功能,是终端软件部署与管理的关键通道。覆盖软件商店启动、页面加载、应用下载、安装、卸载、搜索、自身更新等全部业务场景。

qq_39496637的博客 293

【AI 开发从入门到进阶 · 10】收官篇:LoRA 微调、模型评估、推理加速与生产部署全链路

本文系统梳理了大模型微调与生产落地的全流程,从决策是否微调、优选LoRA技术方案,到代码实现、效果评估、推理加速与FastAPI服务封装,最终构建可迭代的生产级AI系统。强调“逐级升级”原则,倡导以数据闭环驱动优化,避免技术冲动。全系列贯穿工程化思维,提供可复用模板与实战建议,助力开发者从模型训练迈向稳定可用的AI服务部署。

信息安全领域优质创作者|操作系统领域专家 121

LangGraph(03):状态归约、并行更新与消息管理

并行节点写入报错?历史消息无法清理?本文拆解 LangGraph 状态归约与消息增删改机制,带你精确控制复杂工作流状态。

专注于 Agent 工程、AI 产品、Harness Engineering、LLM 算法等方向,OpenMathModel、Nivik 等开源项目作者 128

ARIA规范

ARIA用来补充原生HTML缺失的语义,原则:优先原生标签,ARIA仅做补充。 ARIA角色role:定义组件身份,分为地标角色、构件角色、文档角色;构件角色用于自定义弹窗、tab、下拉菜单等复杂组件; ARIA状态与属性:以aria-开头,描述组件实时状态;常用:aria-label、aria-labelledby、aria-describedby、aria-hidden、aria-expanded、aria-selected、aria-modal、aria-live; 常用场景:图标按钮用aria-l

2401_83227843的博客 461

LangGraph 的分离思想总结

LangGraph 的分离思想,本质上是对"高内聚、低耦合"这一经典工程原则在 LLM 应用领域的落地。它通过状态与逻辑分离、节点职责分离、控制流与执行分离、计算与持久化分离、编排与实现分离五个层面,把一个难以维护的"大黑盒"拆解成一组可组合、可测试、可观测的部件。理解这套分离思想,比记住 API 更重要——因为当你面对新的智能体场景时,真正指导你做出合理拆分的,正是这些分离原则。

张晨光老师的播客 392

Java基础:泛型、类型擦除与 PECS 原则

泛型允许类、接口和方法使用类型参数,把许多类型检查提前到编译期,减少显式类型转换,提高代码复用性。例如。

cjpabc的博客 461

To-Do List 的「修改」功能与 CSS 定位

买牛奶</td><td index="1">写作业</td><td index="2">跑步

2401_89953644的博客 297

第2讲:提示注入攻击——原理与防御

提示注入是攻击者通过恶意指令绕过AI系统规则的安全威胁,分为直接注入(如覆盖指令、角色扮演越狱)和间接注入(藏于文档或搜索结果中)。防御需三重机制:检测(识别高危模式与多轮诱导)、加固(设置优先级、随机分隔符、锁定输出)、净化(清除控制字符、编码、截断超长输入)。结合上下文分析与多模态处理,可有效防范编码绕过、过度净化等陷阱。核心理念:防御需检测、加固、净化联动,筑牢AI应用安全防线。

sandaoliuge的博客 274

TypeError: must be str, not list

【代码】TypeError: must be str, not list。

Forerunner and Successor 先駆者と後継者 56

Java Arrays.asList 常见坑详解|UnsupportedOperationException、数组联动、基本类型 bug

解析 Arrays.asList 常见开发陷阱,演示 UnsupportedOperationException、底层数组引用共享、基本类型数组问题,区分 Arrays 内部 ArrayList 与 java.util.ArrayList,给出数组转 List 的各种场景正确代码。

weixin_42617033的博客 494
上一篇: docker搭建C语言开发环境
下一篇: 数据库修仙筑基篇三——raft重要概念
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我在数据库世界里修仙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值