xiaohack's Blog - Kafka
type: channel
link: https://blog.xiaohack.org/tag/kafka/
items: Fluss在阿里双11万亿规模场景下的落地实践
items: Linux 环境下，Apache DolphinScheduler 如何驱动 Flink 消费 Kafka 数据？
items: 从Kafka到AutoMQ：爱奇艺实时流数据架构演进
items: 自建埋点分析系统的成本对比（含 ClkLog 开源方案）
items: Envoy 可观测性实战：日志、指标与链路追踪的完整落地
items: [独立开发] 带娃写代码的觉悟：删掉 Redis 和 Kafka，我用“喊一嗓子”解决了高并发
items: 是微服务架构不香还是云不香？
items: 数据接入提效 90%，存储成本降 70%，京能集团用 TDengine 实现储能数据毫秒级响应
items: [开源] 写一次代码，适配 6 种 MQ？ Go 统一消息中间件适配层 正式版发布

Fluss在阿里双11万亿规模场景下的落地实践
type: item
date: 2026-01-30T18:18:39+08:00
description: 摘要：本文整理自阿里采集分析平台工程技术负责人 吴宝国 老师，在 Flink Forward Asia 2025 城市巡回深圳站中的分享。Tips：关注「公众号」回复 FFA 2025 查看会后资料～大家好，我是来自阿里集团平台技术部数据技术与产品部的吴宝国。今天非常荣幸能在这里跟大家分享我们在阿里内部大规模落地 Fluss 的一些实践经验。首先简单介绍一下我们团队。我们团队主要负责集团内部统一的用户行为采集与分析平台，也就是大家常说的 A+ 平台。我们的核心职责是为手淘、钉钉、高德、饿了么等众多集团内应用提供端到端的用户行为数据采集、处理、分析及服务能力。在底层，我们构建了覆盖 Web、小程序、APP（包括 Android、iOS、PC、IOT、鸿蒙、VR 等）以及服务端的全场景采集 SDK 矩阵。在此之上，我们不仅采集用户的行为日志（比如点击、曝光、滑动等），还会融合业务数据（如用户标签、商品信息、订单数据等），构建服务于整个集团的流量域数据公共层。最终，我们通过分析产品帮助业务团队洞察用户行为，驱动运营和产品决策，例如提升广告效果、优化用户体验等。为了支撑这一庞大体系的实时性需求，我们引入了开源流存储系统 Fluss 作为核心的日志数据实时采集通道。接下来，我将从为什么选择 Fluss、如何保障大规模落地稳定性、具体业务实践案例以及未来规划四个方面展开分享。一、为什么选择 Fluss？——解决两大核心痛点在引入 Fluss 之前，我们的实时数据架构长期面临两个根本性挑战。（1）成本高昂：行式消息队列导致资源浪费严重我们过去主要依赖阿里内部的行式消息队列 TT（TimeTunnel）。以手淘的实时流量公共层为例，这张表包含了首页、闪购、搜索等多个业务的数据。每个下游业务（比如推荐系统）都需要一个独立的 Flink 作业来消费这张全量表，然后在作业内进行过滤，只保留自己关心的部分。这种模式带来了三重成本问题：存储与流量成本倍增：计费通常基于读写流量。即使每个业务只关心 1% 的数据，也需要为 100% 的全量数据付费。如果有 N 个业务，就要支付 N 倍的费用。Flink CU 资源浪费：Flink 作业需要消耗大量计算单元（CU）来读取、反序列化并丢弃无用的数据。很多时候，作业空跑不做任何逻辑处理，但依然产生高昂开销。字段冗余读取：一张表可能包含数百个字段，但单个业务往往只需要其中几个。行式存储迫使消费者读取整行数据，造成巨大的 IO 和网络带宽浪费。Fluss 通过其三大核心能力完美解决了上述问题：多级分区（Multi-level Partitioning）：支持按业务、按场景等维度对数据进行精细划分。过滤下推（Filter Pushdown）：消费者可以在订阅时声明过滤条件，数据在源头即可被精确过滤，避免全量拉取。列式存储（Columnar Storage）：允许消费者只读取所需的字段，极大降低数据消费量和 Flink CU 消耗。（2）湖流割裂：Lambda 架构的运维与一致性困境业界经典的 Lambda 架构虽然能同时提供实时和离线视图，但维护两套独立的批处理和流处理链路，带来了开发、运维成本高企以及数据统计口径不一致等问题。随着数据湖技术（如 Paimon、Hudi）的发展，湖仓一体架构成为主流，但它通常只能提供分钟级的数据新鲜度。对于搜索、推荐等要求秒级延迟的核心场景，我们仍需引入 Kafka 这类流式中间件，这实际上又回到了 Lambda 架构的老路，导致“湖”与“流”的割裂。Fluss 的出现为我们提供了一个统一的解决方案：它既能作为高性能的流存储提供秒级数据新鲜度，又能通过其内置的分层存储（Tiering）能力无缝对接数据湖（如阿里内部的 Alake），真正实现了“湖流一体”，消除了双架构的痛点。二、首次双11落地情况：大规模生产验证2025 年的双 11 是 Fluss 在阿里集团的首次大促实战。目前，Fluss 已稳定服务于淘天（含通天塔、阿里妈妈等）、集团数据公共层、饿了么、淘宝闪购、高德、阿里影业等多个核心业务，核心场景主要集中在搜索、推荐、流量等。在本次双十一期间，Fluss 展现了强大的承载能力：数据量：4 PB/天TPS峰值：1 亿BPS峰值：100 GiB/s这些数据充分证明了 Fluss 在大规模、高并发场景下的稳定性和可靠性。三、集群部署架构阿里集团内部的业务特点与云上有所不同，因此我们的部署架构也进行了针对性设计。我们采用了“大集群 + 区域化部署”的模式。不同地域（如张北、上海）拥有独立的 Fluss 集群，而同一地域内的不同业务（如高德、钉钉、淘天）则通过数据库（DB）级别进行逻辑隔离。数据持久化在阿里自研的分布式文件系统 盘古 上，并通过 Tiering Service 同步至…

Linux 环境下，Apache DolphinScheduler 如何驱动 Flink 消费 Kafka 数据？
type: item
date: 2026-01-28T11:14:40+08:00
description: 已经在虚拟机部署好Apache DolphinScheduler了，想尝试下在Flink新建一个Flink节点，然后用Flink消费Kafka数据。Apache DolphinScheduler用的是单机部署，具体操作可以参考官方文档：DolphinScheduler | 文档中心(https://dolphinscheduler.apache.org/zh-cn/docs/3.3.2/guide/in...).前置条件：已经安装Java 11、DolphinScheduler 3.3.2、Flink 1.18.1、Kafka 3.6.0，Zookeeper用Kafka内置的。建议这些安装都下载二进制的安装包到虚拟机安装，用命令安装的不可控，我下载的二进制包如下：配置好Flink的环境变量1、编辑环境变量：sudo vim ~/.bashrc增加Flink的路径2、使环境变量生效：#使环境变量生效 source ~/.bashrc #查看环境变量 echo $Flink_HOME修改Kafka、Flink以及DolphinScheduler的配置文件因为用的是虚拟机，为了让外面的主机能够访问到虚拟机的网络，需要修改下配置文件修改Kafka配置：找到Kafka安装包下的config文件夹，修改config下的server.properties文件，修改listeners是为了外面的主机能够访问到虚拟机的Kafka，还有把advertised.listeners改成虚拟机地址，写样例的时候能连上虚拟机的Kafka地址，不然默认连localhostbroker.id=0 listeners=PLAINTEXT://0.0.0.0:9092 #192.168.146.132修改成虚拟机ip advertised.listeners=PLAINTEXT://192.168.146.132:9092修改Flink配置：找到Flink安装包下的conf文件夹，修改conf下的Flink-conf.yaml文件，把里面所有的localhost地址全部改成0.0.0.0，以便主机能访问到虚拟机的Flink。还有增加jobmanager和taskmanager的内存jobmanager.rpc.address: 0.0.0.0 jobmanager.bind-host: 0.0.0.0 jobmanager.cpu.cores: 1 jobmanager.memory.process.size: 1600m taskmanager.bind-host: 0.0.0.0 taskmanager.host: 0.0.0.0 taskmanager.memory.process.size: 2048m taskmanager.cpu.cores: 1修改Apache DolphinScheduler的配置文件，从Apache DolphinScheduler的启动脚本文件dolphinscheduler-daemon.sh可以看出，配置环境变量用的是bin/env文件夹下的dolphinscheduler_env.sh。查看dolphinscheduler-daemon.sh文件：修改dolphinscheduler_env.sh文件，新增JAVA、Flink路径：#修改成自己的JAVA、Flink路径 export JAVA_HOME=/data/jdk-11.0.29 export Flink_HOME=/data/Flink-1.18.1关闭防火墙，启动应用启动应用，包括Zookeeper、Kafka、Flink以及Apache DolphinScheduler。#关闭防火墙 sudo systemctl stop firewalld # 在 Flink 根目录下，执行以下命令启动 Flink 集群 bin/start-cluster.sh # 启动 ZooKeeper bin/zookeeper-server-start.sh config/zookeeper.properties & # 启动 Kafka 服务器 bin/Kafka-server-start.sh config/server.properties & #创建 Kafka 主题 bin/Kafka-topics.sh --create --topic test --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1 #使用命令行生产者发送消息 bin/Kafka-console-producer.sh --topic test --bootstrap-server localhost:909…

从Kafka到AutoMQ：爱奇艺实时流数据架构演进
type: item
date: 2026-01-26T16:02:24+08:00
description: 从Kafka到AutoMQ：爱奇艺实时流数据架构演进概述本文详细介绍了爱奇艺在处理大规模实时流数据时，从传统Kafka架构向AutoMQ演进的技术历程。为了解决私有云环境下集群扩缩容难、资源利用率低以及运维成本高等挑战，爱奇艺开发了Stream平台与Stream-SDK，实现了业务与底层存储的彻底解耦。随后，公司引入公有云服务并最终切换至基于存算分离架构的AutoMQ，利用其单副本存储和秒级弹性的特性，显著提升了系统的灵活性。这一系列的架构升级不仅优化了数据治理体系，还成功将运营成本降低了70%以上。目前，爱奇艺正持续扩大AutoMQ的应用规模，以进一步实现降本增效的长期目标。背景Kafka因其高吞吐、低延时、可扩展的特性，在出现之后迅速成为流数据存储的标准组件，广泛应用于实时大数据场景。爱奇艺的流数据服务也主要基于Kafka构建，随着实时大数据应用越来越广泛，Kafka集群数量、规模越来越大，面临扩缩容繁琐、成本高、难治理等诸多问题与挑战。为解决这些问题，我们进行了Kafka服务化、上云、迁移AutoMQ等一系列探索。本文将介绍爱奇艺Kafka从私有云迈向公有云、从Kafka到AutoMQ的探索与实践。流数据在爱奇艺的应用在爱奇艺，流数据的存储组件使用的是Kafka，计算组件主要使用的是Flink，流数据相关的典型数据通路如图1所示，主要包括如下环节：数据集成：Pingback(端上投递日志)、后端日志、数据库binlog、指标等持续产生的流数据，实时写入数据总线Kafka。数据仓库：由Flink程序将数据引入到实时（流式）、离线（批式）数仓。在实时数仓中，数据仍然以流数据形态存储在Kafka中，并通过Flink构建实时数仓各层数据。在离线数仓中，流数据将会聚集成批数据存储在Iceberg中，再由 Flink增量消费Iceberg构建离线数仓各层数据。实时数仓具备秒级延时，离线数仓具备分钟级以上延时。数据开发：数仓的数据通过数据开发平台应用到各业务场景。在实时计算中Kafka也会作为中间流数据的存储用于任务之间的解耦。数据应用：数据广泛应用到爱奇艺的推荐、搜索、广告、报表等等场景中。数据的价值随着延时增大快速衰减，为了数据价值最大化，近几年主要应用场景都已切换到流数据。Kafka作为流数据的存储承担数据集成到大数据体系的数据总线、实时数仓存储、实时任务之间解耦等角色。流数据存储服务：从管集群到管数据爱奇艺的流数据服务最初以Kafka集群为核心构建，提供集群生命周期管理、Topic管理、消费监控等基础能力。随着业务规模扩大、集群数量和数据量持续增长，逐渐暴露出以下问题：业务与集群强耦合：业务代码直接依赖Kafka地址访问集群，一旦需要迁移或调整集群，必须修改业务代码并重新上线，不灵活。同时也无法从平台侧统一识别和监控各业务的读写行为。缺乏统一的数据与schema管理：平台没有管理数据描述、schema、数据归属等元数据信息，无法提供数据查找功能，不利于跨团队的数据理解、复用与治理。主备数据管理缺失：对重要数据，业务侧通常配置主备链路，但平台侧缺乏对主备关系的统一管理，难以做到一致性保障与故障切换治理。为了解决上述问题，我们将流数据存储服务升级到了如图2所示的架构，由Stream平台、Stream-SDK、存储组件三部分构成。先介绍下Stream平台，Stream-SDK和存储组件后面介绍。Stream平台由“集群管理”和“数据管理”两大模块组成。集群管理负责集群生命周期与底层资源的统一管理，侧重运维侧能力。数据管理是平台的核心，以“数据为中心”构建，面向数据开发人员提供统一的数据视图和管理能力，核心功能如下：逻辑队列：原先“集群+Topic”定位数据的方式，升级为基于“项目+队列（Topic）”的逻辑命名方式，集群仅作为队列的一个属性，消除业务对具体集群的依赖。逻辑队列还支持同时绑定主备两个集群，结合Stream-SDK可实现主备链路的一键切换。Schema管理：支持为队列配置schema，并自动同步至大数据元数据中心，使队列能够在数据开发平台中自动映射为逻辑表，使用SQL直接处理流数据。数据地图：提供队列的多维度查询与检索能力，支持在线申请和授权使用队列，简化跨团队的数据查找和复用流程。数据血缘：基于Stream-SDK自动上报的读写端信息，构建应用级的读写血缘链路，帮助快速定位上下游数据关系及影响范围。Stream-SDK：统一的流数据读写客户端Stream-SDK是平台提供的统一数据访问客户端，封装了底层原生客户端，兼容Kafka协议和RocketMQ。业务仅需配置“项目+队列”，即可完成数据读写，无需关注具体集群地址或认证方式，从而实现业务代码与底层集群的彻底解耦。Stream-SDK的数据读写流程如图3所示，主要包括…

自建埋点分析系统的成本对比（含 ClkLog 开源方案）
type: item
date: 2026-01-26T15:06:21+08:00
description: 很多团队在业务发展到一定阶段后，都会认真评估一次：用户行为分析系统，是继续用现成产品，还是自己搭一套？实际上，当企业需要埋点分析时，往往已经没有太多时间成本可投入。业务方希望尽快看到数据结果，管理层关注投入产出比，而完全从零自建埋点系统，周期长、风险高、不可控。因此，基于成熟开源方案快速上线，再按需求自己二开，是目前更常见、也更可控的一种选择。这篇文章不讨论“埋点的重要性”，只做一件事：以自建埋点分析系统为参照，给出一个成本参考，并对比基于 ClkLog 开源方案的实际投入。完全自建一套埋点分析系统成本通常在几十万，且建设周期长、不可控因素多。基于ClkLog开源方案搭建首期成本可控制在几万，最快一周完成部署集成，可以快速交付使用，并具备持续扩展的能力。一、自建埋点分析系统，通常需要哪些模块？很多团队低估了“自建”的工作量，下面只列最基础、不可回避的部分：1.数据采集层（SDK + 埋点规范）这个阶段往往被低估，但实际上 SDK 会长期伴随业务演进，需要持续维护。2.数据接入与处理层核心目标是稳定接住数据：常见技术栈包括接入服务 + Kafka / MQ。3.数据存储层通常会选择 ClickHouse / Doris / Druid 这类分析型数据库，同时需要设计分区、冷热数据策略。4.复杂分析计算这是自建中最耗精力的部分，很多团队会发现：统计不难，难的是保证分析口径正确且性能可用。5.管理后台与可视化这部分前端和交互成本往往被严重低估。6.运维与长期维护系统上线只是开始，后续还包括各项调优、异常排查等运维工作。二、为什么很多团队不会选择「完全自建」？问题不在“能不能做”，而在是否划算。●早期业务验证阶段，数据系统很难直接创造业务价值●自建系统容错成本高，试错周期长因此，越来越多团队会选择：在成熟的开源埋点分析系统基础上建设，而不是从零开始。三、ClkLog开源方案能解决什么问题？ClkLog提供了一套可直接落地的开源埋点分析方案，不依赖第三方SaaS服务。全面覆盖了埋点系统中最重、最复杂的核心能力：1.数据采集层支持神策SDK与自研鸿蒙SDK2.数据接受层进行日志数据接收与存储3.数据处理层进行数据处理、归档等服务4.数据存储层使用clickhouse进行大量数据查询5.数据可视化内置多种成熟分析模型，开箱即用企业无需从零搭建底层能力，只需要围绕自身业务场景完成部署、运维和少量定制，即可形成一套可用的自有埋点分析系统。四、基于 ClkLog，企业实际需要投入哪些成本？1. 基础运行环境（参考）以 ClkLog 社区版为例，在 1万日活应用规模下，采用Docker方式部署，单台服务器即可满足基础使用需求。推荐配置参考：8核CPU；32GB内存在常见的云厂商环境中，约1-2万/年，即可覆盖服务器、云盘、流量、备份等成本。2. 软件部署与集成●获取ClkLog代码（Github/Gitee）●自行部署ClkLog服务（docker部署最快10分钟完成）●接入埋点SDK（兼容web/小程序/iOS/安卓等）●常规运维数据库和服务整体实施周期短，最快一天即可完成部署并交付使用。3. 业务层面的工作●埋点规范梳理●事件与指标定义●少量业务定制ClkLog已经内置十几种行业标准分析模型，可供业务直接开箱使用。若还有更多定制业务需要分析，可以通过自定义事件或二次开发来实现，与完全自建相比，省去的是部门团队沟通、大量底层系统设计与长期维护成本。五、写在最后对于大多数团队来说，先把系统跑起来、用起来、产生价值，比一开始追求完美更重要。如果团队希望：●完全掌控数据●又不想长期投入基础设施研发●把精力更多放在业务分析而不是系统本身那么，基于成熟开源方案搭建自己的埋点分析系统，是一个性价比较高、风险更可控的选择。

Envoy 可观测性实战：日志、指标与链路追踪的完整落地
type: item
date: 2026-01-26T11:20:30+08:00
description: 前言本节详细聊一下基于envoy的可观测性日志首先是日志，配置日志的方式也很简单static_resources: listeners: - name: ingress_listener address: socket_address: address: 0.0.0.0 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http ... access_log: - name: envoy.access_loggers.stdout typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog log_format: text_format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %BYTES_SENT% %DURATION% %REQ(X-REQUEST-ID)% \"%REQ(USER-AGENT)%\" \"%REQ(X-FORWARDED-FOR)%\" %UPSTREAM_HOST% %UPSTREAM_CLUSTER% %RESPONSE_FLAGS%\n" 该配置是将日志输出在控制台，也可以直接输出为文件，然后通过工具采集走path: /var/log/envoy/access.log也可以直接将日志输出至kafka，并且按比例采集、只采集4xx、5xx等都可以配置，这里就不在赘述了admin管理页面envoy有默认的admin页面，方便查看统计信息、打开某些功能的开关等admin: address: socket_address: address: 0.0.0.0 port_value: 9901 打开9901页面：可以查看相关的统计信息、也可以打开某些开关，功能还是很丰富的merics接入prometheus打开了admin之后，就默认提供了相关的prometheus stats http://10.105.148.194:9901/stats/prometheus这时只需在k8s集群外弄一个prometheus，并且采集该envoy即可prometheus.ymlglobal: scrape_interval: 5s evaluation_interval: 5s rule_files: - /etc/prometheus/*.rules scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: "envoy" metrics_path: /stats/prometheus static_configs: - targets: ["10.105.148.194:9901"] docker run -d --name prometheus \ -p 9090:9090 \ -v ./prometheus.yml:/etc/prometheus/prometheus.yml \ -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \ registry.cn-beijing.aliyuncs.com/wilsonchai/prometheus:v3.5.0traces接入jaegerjaeger的安装可以参考这里： opentelemetry全链路初探--埋点与jaegerjaeger启动之后，改造一下envoy的配置，这里要特别注意，不同版本的配置不一样，我这里envoy的版本是：v1.32static_resources: listeners: - name: ingress_listener filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: ... tracing:…

[独立开发] 带娃写代码的觉悟：删掉 Redis 和 Kafka，我用“喊一嗓子”解决了高并发
type: item
date: 2026-01-25T09:03:52+08:00
description: 大家好，我是《交易学徒》的作者。简单介绍下背景：我现在的核心身份是带两个孩子的全职奶爸，副业才是趁着孩子睡着后，在键盘上敲敲打打的独立开发者。对于我这种“碎片化时间”开发者来说，运维复杂度就是最大的敌人。几年前写后端，我也迷信“标准答案”：做个服务，起手就是 Docker 编排，Redis 做缓存，Kafka 做解耦，微服务先分几个出来。结果往往是，功能没写几个，光是调网络、修连接超时、查中间件报错，就把孩子午睡的那宝贵两小时耗光了（那时候还没孩子）。在开发后端时，我陷入了深思：“对于一个追求极致性能、但只有一个人维护的系统，所谓的‘工业级架构’真的是解药吗？还是毒药？”最终，我做了一个违背祖宗的决定：做减法。 我删除了 Redis ，移除了 Kafka ，把整个微服务集群塌缩成了一个 Rust 单体应用。今天想聊聊这背后的思考过程。一、 复杂度的守恒与转移 我的业务场景看似简单，实则牵一发而动全身。一个简单的“用户平仓”动作，就像推倒了第一块多米诺骨牌：核心域：结算盈亏，改余额，写数据库。（必须马上做）通知域：给前端发个弹窗通知“平仓成功”。（晚 0.1 秒没关系）营销域：判断有没有触发“五连胜”、“以小博大”成就，发奖励。（晚 1 秒没关系）统计域：计算交易评分，统计分数或者更新等级与交易报表。（晚几秒都行）在“标准架构”里，我们需要引入 消息队列 (MQ) 来解耦这些逻辑。 但引入 MQ 本质上并没有消除复杂度，只是将“代码复杂度”转移成了“运维复杂度”。对于团队，运维复杂度可以分摊给同事；但对于我，这意味着我不仅要写代码，还得修服务器。Rust 给了我另一个选择：利用它极高的性能，把“运维复杂度”重新压回“架构设计”里，用最朴素的方式解决问题。二、 内存即总线：构建“喊一嗓子”的架构 我利用 Rust 的内存通道特性，构建了一个“超光速大喇叭”。 我不请求数据，我只发布事实。这个过程，可以用一个生活化的场景来描述： 定义世界的真相 (The Truth) 我不写复杂的 XML 或 JSON 定义，我只是在代码里列了一张“事实清单”： 📄 事实 A：有人平仓了（包含：是谁、赚了多少、单号是多少）📄 事实 B：有人购买商品了📄 事实 C：AI 分析完成了编译器会盯着这张清单，保证我发出的每一个“事实”都是格式正确、童叟无欺的。 极简的生产者 (Fire and Forget) 在核心交易逻辑里，当数据库事务提交成功后，我只需要做一件事：拿着大喇叭喊一嗓子。 传统架构 (Kafka) 是这样的：交易模块 -> 打包数据 -> 建立 TCP 连接 -> 三次握手 -> 发送给 Kafka 集群 -> 等待 ACK -> 结束 (这中间任何一步网络抖动，都得处理异常)我的单体架构是这样的：交易模块 -> 喊：“老王平仓赚了 100 块！” -> 结束 (纯内存操作，纳秒级完成，快到像是没有发生过) 静默的消费者 (Sidequest Logic) 我把原本分散在微服务里的逻辑，变成了几个坐在角落里的“隐形工人”。 比如 “营销服务”，它就像一个在角落里旁听的记分员：它平时不说话，只听大喇叭。一听到 “老王平仓赚了 100 块”，它立马翻开小本本查历史。发现老王已经连赢 4 把了，加上这把正好 5 把。于是它默默地给老王发了一个“五连绝世”的徽章。整个过程，核心交易模块完全不知情，也完全不用等待，它喊完那一嗓子就去服务下一个用户了。三、 深度思考：关于“不可靠”的权衡 很多朋友可能会问：“没有 Kafka 把消息存到硬盘里，万一服务器断电了，你喊的那一嗓子不就丢了吗？”是的，这是整个架构思考中最痛苦，也是最关键的取舍。 我问了自己两个问题：Q1：我的程序崩溃概率有多大？ Rust 以安全著称，只要代码写得不离谱，它极难崩溃（ Panic ）。这比 Java 的内存溢出或 Python 的运行时错误要稳健得多。Q2：丢失数据的代价是什么？我们可以把数据分成两类：💰 钱（核心数据）： 余额、订单状态。处理方式： 必须落袋为安。 直接写死在数据库里，绝不依赖“大喇叭”。🎁 气氛（衍生数据）： 弹窗通知、成就徽章、达标奖励、统计报表。处理方式： 听天由命。 如果真的赶上万年不遇的服务器着火，用户少收到了一个“五连胜”的弹窗，或者报表少统计了一笔，天会塌吗？不会。结论： 为了 0.001% 的极端掉电风险，去让 99.99% 的时间里的系统背负沉重的中间件包袱，对于独立开发者来说，这是一笔亏本买卖。四、 结语 当我们谈论“高性能”时，往往想到的是复杂的集群、昂贵的服务器。 但 Simple is fast. （简单即快）现在的《交易学徒》后端，就是一个 20MB 的小文件。❌ 没有 Docker 容器编排❌ 没有 虚拟机调优❌ 没有 Red…

是微服务架构不香还是云不香？
type: item
date: 2026-01-24T18:17:57+08:00
description: 这两天技术圈里热议的一件事就是Amazon的流媒体平台Prime Video在2023年3月22日发布了一篇技术博客《规模化Prime Video的音视频监控服务，成本降低90%》，副标题：“从分布式微服务架构到单体应用程序的转变有助于实现更高的规模、弹性和降低成本”，有人把这篇文章在五一期间转到了reddit 和 hacker news 上，在Reddit上热议。这种话题与业内推崇的微服务架构形成了鲜明的对比。从“微服务架构”转“单体架构”，还是Amazon干的，这个话题足够劲爆。然后DHH在刚喷完Typescript后继续发文《即便是亚马逊也无法理解Servless或微服务》，继续抨击微服务架构，于是，瞬间引爆技术圈，登上技术圈热搜。今天上午有好几个朋友在微信里转了三篇文章给我，如下所示： 《微服务是不是个蠢主意？》 《单体回归？亚马逊放弃用于视频监控的微服务 》 《从微服务转为单体架构、成本降低 90%，亚马逊内部案例引发轰动》 看看这些标题就知道这些文章要的是流量而不是好好写篇文章。看到第二篇，你还真当 Prime Video 就是 Amazon 的全部么？然后，再看看这些文章后面的跟风评论，我觉得有 80%的人只看标题，而且是连原文都不看的。所以，我想我得写篇文章了……原文解读要认清这个问题首先是要认认真真读一读原文，Amazon Prime Video 技术团队的这篇文章并不难读，也没有太多的技术细节，但核心意思如下：1）这个系统是一个监控系统，用于监控数据千条用户的点播视频流。主要是监控整个视频流运作的质量和效果（比如：视频损坏或是音频不同步等问题），这个监控主要是处理视频帧，所以，他们有一个微服务主要是用来把视频拆分成帧，并临时存在 S3 上，就是下图中的 Media Conversion 服务。2）为了快速搭建系统，Prime Video团队使用了Serverless 架构，也就是著名的 AWS Lambda 和 AWS Step Functions。前置 Lambda 用来做用户请求的网关，Step Function 用来做监控（探测器），有问题后，就发 SNS 上，Step Function 从 S3 获取 Media Conversion 的数据，然后把运行结果再汇总给一个后置的 Lambda ，并存在 S3 上。整个架构看上去非常简单 ，一点也不复杂，而且使用了 Serverless 的架构，一点服务器的影子都看不见。实话实说，这样的开发不香吗？我觉得很香啊，方便快捷，完全不理那些无聊的基础设施，直接把代码转成服务，然后用 AWS 的 Lamda + Step Function + SNS + S3 分分钟就搭出一个有模有样的监控系统了，哪里不好了？！但是他们遇到了一个比较大的问题，就是 AWS Step Function 的伸缩问题，从文章中我看到了两个问题（注意前方高能）： 需要很多很多的并发的 AWS Step Function ，于是达到了帐户的 hard limit。 AWS Step Function 按状态转换收费，所以，贵得受不了了。 注意，这里有两个关键点：1）帐户对 Step Function 有限制，2）Step Function 太贵了用不起。然后，Prime Video 的团队开始解决问题，下面是解决的手段：1） 把 Media Conversion 和 Step Function 全部写在一个程序里，Media Conversion 跟 Step Function 里的东西通过内存通信，不再走S3了。结果汇总到一个线程中，然后写到 S3.2）把上面这个单体架构进行分布式部署，还是用之前的 AWS Lambda 来做入门调度。EC2 的水平扩展没有限制，而且你想买多少 CPU/MEM 的机器由你说了算，而这些视频转码，监控分析的功能感觉就不复杂，本来就应该写在一起，这么做不更香吗？当然更香，比前面的 Serverless 的确更香，因为如下的几个原因： 不再受 Step Function 的限制了，技术在自己手里，有更大的自由度。 没有昂贵的 Step Function 云成本的确变得更低了，如果你把 Lambda 换成 Nginx 或 Spring Gateway 或是我司的 Easegress，你把 S3 换成 MinIO，你把 SNS 换成 Kafka，你的成本 还能再低。 独立思考好了，原文解读完了，你有自己的独立思考了吗？下面是我的独立思考，供你参考：1）AWS 的 Serverless 也好， 微服务也好，单体也好，在合适的场景也都很香。这就跟汽车一样，跑车，货车，越野车各有各的场景，你用跑车拉货，还是用货车泡妞都不是一个很好的决定。2）这篇文章中的这个例子中的业…

数据接入提效 90%，存储成本降 70%，京能集团用 TDengine 实现储能数据毫秒级响应
type: item
date: 2026-01-22T17:36:30+08:00
description: 小T导读：京能集团在储能安全管理平台中采用 TDengine TSDB 作为底层时序数据库。依托 TDengine 企业版的零代码数据写入平台，来自全国 28 家电化学储能电站的数据能够按照统一编码规则高效接入 TDengine 时序数据库中，实现了稳定、高性能的数据采集与管理。在此基础上，借助 TDengine TSDB Flink Connector，系统可快速、稳定地从数据库中读取海量数据，开展实时分析与智能处理，充分释放数据的潜在价值。本文将结合该项目的实践过程，为大家带来深入分享与参考。项目背景京能集团储能安全管理平台共接入全国 28 家电化学储能电站，累计测点达 270 万个，由四个平台公司分别负责数据传输与汇聚。系统需要支撑大规模的数据统计分析、事件报警与安全预警，对底层数据库的性能与稳定性提出了极高要求。鉴于电化学储能项目采集点数量庞大（270 万点）、锂电池热失控的超前预警技术复杂等因素，传统关系型数据库已无法满足高并发写入与海量数据存储的需求。由于这些数据具备时间序列写入、格式固定、写入量巨大等典型特征，我们最终选择采用时序数据库作为系统核心数据底座。应用实际落地在充分调研国内多款时序数据库产品后，我们发现，从国内目前的实际情况分析，TDengine TSDB 已成为众多企业在海量数据高速存储、处理与调用场景中的首选方案。基于其成熟的技术体系与稳定的性能表现，我们最终选定 TDengine TSDB 作为平台的底层时序数据库，并结合 Kafka 与 Flink 构建了完整的数据流处理体系，实现了数据的高效传输与实时计算，顺利达成项目预期目标。以下是架构简图：TDengine TSDB 支持多种写入方式SQL 语言写入 ：https://docs.taosdata.com/basic/insert/无模式写入：https://docs.taosdata.com/develop/schemaless/参数绑定方式：https://docs.taosdata.com/develop/stmt/企业版的零代码数据写入— taosExplorer 数据接入功能：https://docs.taosdata.com/advanced/data-in/项目中涉及多个 Kafka 集群、数十个需要接入的 topic。我们重点采用了 TDengine 企业版的零代码数据写入能力，实现了从 Kafka 到 TDengine TSDB 的高效对接。该功能支持灵活配置类似 ETL 的复杂自定义选项，极大简化了数据接入流程和时间，而且数据接入性能完全达到了项目要求。为了保证数据的合理性，我们出台了《京能集团电化学储能电站安全管理平台和储能电站设备标识编码规则》，通过标准的 kks 编码在 taosX 对 Kafka 数据进行了有效过滤和清理，最终写入 TDengine TSDB。kks 部分编码实例如下：下图为数据过滤、转换等规则设置：此外，taosX 数据接入还支持多节点高可用配置。只需在多台 taosX 上部署相同的 Kafka 数据接入任务，并设置相同的 groupId，即可自动实现任务高可用，确保数据接入的连续性与稳定性。同时，TDengine 还提供完善的 taosX 任务监控机制，可直接通过 Grafana 一键配置，快速生成可视化监控图表：超级表 + 子表的使用TDengine TSDB 结合“一个数据采集点一张表”的设计理念，引入了具有创新性的“超级表”机制，从根本上解决了大规模时序数据结构不统一、聚合困难、运维复杂等问题。每个采集点的数据独立存储，天然具备写入无锁、数据顺序追加、块状连续存储等优势。这种设计方式不仅提升了写入与查询性能，还带来了极高的数据压缩效率。TDengine TSDB 支持对超级表标签进行动态的添加、修改与删除操作，满足设备属性变更、系统扩展等业务需求。计算、分析处理在 Flink 计算平台上，我们借助 TDengine TSDB 企业版提供的 Flink 连接器——TDengine TSDB Flink Connector（https://docs.taosdata.com/advanced/data-publisher/Flink/），实现了与 TDengine TSDB 的无缝集成。该连接器可高效、稳定地从 TDengine TSDB 中读取海量时序数据，并在此基础上进行全面、深入的分析处理，充分挖掘数据的潜在价值，极大地提升数据处理的效率和质量。Flink CDC 主要用于提供数据订阅功能，能实时监控 TDengine TSDB 数据库的数据变化，并将这些变更以数据流形式传输到 Flink 中进行处理，同时确保数据的一致性和完整性。落地效果数据接入便利性：目前我们已接入 20 多个 ka…

[开源] 写一次代码，适配 6 种 MQ？ Go 统一消息中间件适配层 正式版发布
type: item
date: 2026-01-20T21:46:49+08:00
description: 在 Go 业务开发中，我们经常遇到这样的场景： 环境切换：本地开发用 NATS 或 RabbitMQ 贪图轻快，线上却要接入 Kafka 或 AWS SQS 。 代码耦合：业务逻辑被底层 MQ 的 SDK 对象（如 *rocketmq.Producer）绑定，一旦想换驱动，几乎要重写整个消息发送逻辑。 配置坑多：每个 MQ 的参数设置五花八门，一不小心传错了参数，程序却静默运行，等到上线出事才发现配置没生效。 为了解决这些痛点，我发起了 Unified MQ Broker for Go 项目。它就像是 MQ 领域的 "DBAL"（类似于 SQL 领域的 GORM 或数据库驱动层），让你通过一套 API 就能无缝切换多种消息中间件。🚀 v0.2.0 重磅更新经过一段时间的打磨，我们刚刚发布了 v0.2.0 版本。这次更新不只是增加了驱动，更是在“健壮性”和“性能”上做了深度优化：1. 🛡️ 独创“选项追踪” (Option Tracking) 痛点：如果你给 Kafka 传了一个 SQS 的 DeduplicationID，大部分 SDK 会选择静默忽略。 方案：v0.2.0 引入了审计机制。如果底层适配器没有读取你传入的某个配置项，系统会在连接或发布时发出显式警告。彻底告别因拼写错误或参数误用导致的配置无效。 2. ⚡ 高性能“智能序列化” (Smart Serialization) 优化：针对原始 []byte 和 string 数据实现了零拷贝路径，跳过冗余的 json.Marshal。 战果：压测显示，在高吞吐场景下，序列化性能提升了 5 倍以上（单次操作仅需 ~16ns ）。 3. 🏗️ 延迟绑定 (Late Binding) NewBroker 现在仅做静态配置。 真正的网络 IO 、TCP 建连和 SDK 初始化全部推迟到 Connect() 时执行，方便与依赖注入框架（如 Wire ）集成。 4. 🌐 全平台支持目前已完美支持：RocketMQ, Kafka, RabbitMQ, NATS, AWS SQS, GCP Pub/Sub。💻 核心代码预览无论底层是哪种 MQ ，你的业务代码只需要关心这一套统一逻辑：import "github.com/qvcloud/broker" // 切换驱动只需要换一行初始化，业务代码 0 改动 b := rabbitmq.NewBroker(broker.Addrs("amqp://...")) b.Connect() // 注入统一的中间件（如 OpenTelemetry 链路追踪） b.Init(broker.Middleware(otel.Middleware)) // 统一的订阅 API b.Subscribe("orders.created", func(ctx context.Context, event broker.Event) error { fmt.Println("收到订单:", string(event.Message().Body)) return nil // 返回 nil 自动 Ack ，返回 error 自动 Nack/Retry }) // 统一的发布 API b.Publish(context.Background(), "orders.created", &broker.Message{ Body: []byte(`{"id": 1001}`), }) 传送门GitHub: https://github.com/qvcloud/broker 核心理念: 接口驱动、高性能、原生支持 OpenTelemetry 。 如果你也深受 MQ 适配之苦，或者想为你的分布式系统寻找一个更规范的通信抽象，欢迎来试用、吐槽或贡献代码！如果你觉得不错，给个 Star 就是最大的支持。 🌟