系统集成架构设计——打通数据孤岛

引言:数据孤岛的痛 数字化转型后,企业通常会有多个系统: OMS订单系统 WMS仓储系统 ERP财务系统 TMS物流系统 BI报表系统 如果这些系统之间数据不通,就会形成"数据孤岛": 同一个数据,各系统不一致 需要人工在多个系统之间搬运数据 无法获得全局视图 系统集成的目标:让数据自动流转,保持一致。 一、集成架构模式 1.1 三种集成模式对比 模式1:点对点集成 ┌─────┐ ┌─────┐ │ OMS │◄───►│ WMS │ └──┬──┘ └──┬──┘ │ │ │ ┌─────┐ │ └─►│ ERP │◄─┘ └─────┘ 优点 缺点 简单直接 耦合度高 实现快 维护难 扩展性差 模式2:ESB企业服务总线 ┌─────┐ ┌─────┐ ┌─────┐ │ OMS │ │ WMS │ │ ERP │ └──┬──┘ └──┬──┘ └──┬──┘ │ │ │ └────────┼────────┘ │ ┌─────▼─────┐ │ ESB │ │ 企业服务总线│ └───────────┘ 优点 缺点 统一管理 架构复杂 解耦 单点风险 可监控 成本高 模式3:事件驱动架构(推荐) ...

2026-01-29 · maneng

库存数据实时同步:从最终一致性到强一致性

引言 库存数据是供应链的核心数据,需要在多个系统间实时同步。本文将探讨库存同步的技术方案和一致性保障。 1. 库存同步场景 1.1 OMS查询库存 @Service public class InventoryQueryService { @Autowired private InventoryCenterClient inventoryCenterClient; @Cacheable(value = "inventory", key = "#sku + ':' + #warehouseCode") public int queryStock(String sku, String warehouseCode) { return inventoryCenterClient.queryAvailableQty(sku, warehouseCode); } } 1.2 WMS更新库存 入库 → 增加库存 → 推送到库存中心 出库 → 减少库存 → 推送到库存中心 盘点 → 调整库存 → 推送到库存中心 1.3 库存预占 OMS下单 → 预占库存 WMS出库 → 扣减库存 订单取消 → 释放库存 2. 同步技术方案 2.1 主动推送 流程: WMS库存变化 → 发送MQ消息 → 库存中心消费更新 优点: 实时性高 数据准确 缺点: ...

2025-11-22 · maneng

RocketMQ入门03:RocketMQ初识 - 阿里开源消息中间件的前世今生

引言:一个技术选型的故事 2010年,淘宝的技术团队面临一个棘手的问题: 双11大促期间,订单量瞬间飙升100倍,原有的 ActiveMQ 集群直接崩溃。几百万用户的订单消息堆积,下游系统无法处理,整个交易链路几近瘫痪。 这不是简单的扩容能解决的问题。他们需要一个全新的消息中间件,一个真正理解电商业务、能扛住双11洪峰的消息系统。 这就是 RocketMQ 诞生的开始。 一、RocketMQ 的前世:从 Notify 到 MetaQ 1.1 第一代:Notify(2007-2010) 背景问题: - 淘宝业务快速增长,系统解耦需求迫切 - 使用 ActiveMQ,遇到性能瓶颈 - 运维成本高,稳定性不足 Notify 1.0 特点: - 基于 ActiveMQ 5.1 改造 - 增加了消息存储优化 - 简单的集群支持 - 问题:Java 性能瓶颈,10K 消息就卡顿 1.2 第二代:MetaQ(2010-2012) // MetaQ 的设计转变 // 从 JMS 规范 → 自定义协议 // 从 随机读写 → 顺序写入 public class MetaQDesign { // 核心创新:完全顺序写入 CommitLog commitLog; // 顺序写入 ConsumeQueue consumeQueue; // 消费索引 // 借鉴 Kafka 的设计 // 但针对电商场景优化 - 支持事务消息 - 支持定时消息 - 支持消息查询 } MetaQ 的突破: ...

2025-11-13 · maneng

RocketMQ入门02:消息队列的本质与演进

引言:从一个简单的队列开始 在计算机科学中,队列(Queue)是最基础的数据结构之一。它遵循 FIFO(First In First Out)原则,就像排队买票一样,先来的先处理。 // 最简单的队列实现 public class SimpleQueue<T> { private LinkedList<T> items = new LinkedList<>(); public void enqueue(T item) { items.addLast(item); // 入队 } public T dequeue() { return items.removeFirst(); // 出队 } } 这个简单的数据结构,竟然是现代消息队列的起源。让我们看看它是如何一步步演进的。 一、演进阶段1:进程内队列 1.1 最初的需求 在单进程程序中,当我们需要解耦生产者和消费者时,最简单的方式就是使用内存队列: // 生产者-消费者模式 public class InMemoryMessageQueue { private final BlockingQueue<Message> queue = new LinkedBlockingQueue<>(); // 生产者线程 class Producer extends Thread { public void run() { while (true) { Message msg = generateMessage(); queue.put(msg); // 阻塞式入队 } } } // 消费者线程 class Consumer extends Thread { public void run() { while (true) { Message msg = queue.take(); // 阻塞式出队 processMessage(msg); } } } } 特点: ...

2025-11-13 · maneng

RocketMQ入门01:为什么需要消息队列

引言:从一个电商下单场景说起 想象这样一个场景:用户在你的电商平台下单购买了一件商品。看似简单的一次点击,背后却触发了一系列复杂的业务流程: 扣减库存 生成订单 扣减用户积分 发送短信通知 发送邮件通知 增加商家销量统计 记录用户行为日志 触发推荐系统更新 如果采用传统的同步调用方式,会是什么样子? 一、同步通信的痛点 1.1 性能瓶颈 // 传统同步调用方式 public OrderResult createOrder(OrderRequest request) { // 核心业务:100ms Order order = orderService.create(request); // 100ms inventoryService.deduct(request.getSkuId()); // 50ms // 非核心业务:累计 500ms+ pointService.deduct(request.getUserId()); // 100ms smsService.send(request.getPhone()); // 200ms emailService.send(request.getEmail()); // 150ms statisticsService.record(order); // 50ms logService.log(order); // 30ms recommendService.update(request.getUserId()); // 100ms return new OrderResult(order); } // 总耗时:730ms+ 问题分析: 用户需要等待 730ms+ 才能看到下单结果 其中只有前 150ms 是核心业务 580ms 都在等待非核心业务完成 1.2 高耦合问题 // 每增加一个下游系统,都要修改订单服务代码 public OrderResult createOrder(OrderRequest request) { // ... 原有代码 // 新需求:增加优惠券系统通知 couponService.notify(order); // 又要改订单服务! // 新需求:增加大数据分析 bigDataService.collect(order); // 又要改订单服务! } 问题分析: ...

2025-11-13 · maneng

服务间通信:同步调用、异步消息与事件驱动

引子:一次服务雪崩引发的思考 2020年双11凌晨2点,某电商平台订单服务突然不可用,导致用户无法下单。 故障链路: 用户下单 → 订单服务 → 库存服务(超时20秒) → 订单服务线程池耗尽 → 整个系统不可用 问题根源: 订单服务同步调用库存服务(HTTP请求) 库存服务压力大,响应慢(20秒超时) 订单服务线程池耗尽(200个线程全部阻塞) 新的订单请求无法处理,系统崩溃 架构师王明的反思: “同步调用的问题是什么?” “为什么不用异步消息?” “什么场景用同步,什么场景用异步?” 这个案例揭示了微服务通信的核心问题:如何选择合适的通信模式,平衡性能、可靠性、复杂度? 一、通信模式的本质:耦合度与可靠性的权衡 1.1 通信模式的两个维度 维度1:同步 vs 异步 维度 同步通信 异步通信 调用方式 请求→等待→响应 请求→立即返回→回调 阻塞性 调用方阻塞等待 调用方不阻塞 耦合度 强耦合(时间耦合) 弱耦合(时间解耦) 响应时间 快(毫秒级) 慢(秒级或分钟级) 可用性 低(被调用方挂了,调用方也挂) 高(被调用方挂了,消息不丢失) 复杂度 低(简单直接) 高(需要消息队列) 维度2:点对点 vs 发布订阅 维度 点对点(P2P) 发布订阅(Pub/Sub) 调用关系 一对一 一对多 耦合度 强耦合(空间耦合) 弱耦合(空间解耦) 扩展性 差(新增消费者要修改代码) 好(新增消费者不影响发布者) 典型场景 RPC调用 领域事件 1.2 耦合度的四个维度 1. 时间耦合(Temporal Coupling) ...

2025-11-03 · maneng

Redis实战:分布式锁、消息队列、缓存设计

一、分布式锁:从SETNX到Redlock 1.1 为什么需要分布式锁? 场景:秒杀系统的超卖问题 // ❌ 错误:单机锁无法解决分布式超卖 @Service public class SeckillService { @Autowired private ProductRepository productRepository; /** * 秒杀下单(单机锁) */ public synchronized Order seckill(Long productId, Long userId) { // 1. 检查库存 Integer stock = productRepository.getStock(productId); if (stock <= 0) { throw new SoldOutException("商品已售罄"); } // 2. 扣减库存 productRepository.decrementStock(productId); // 3. 创建订单 return orderService.createOrder(productId, userId); } } // 问题: // 假设有3台服务器(Server A、B、C) // T1: Server A:检查库存=1(通过) // T2: Server B:检查库存=1(通过) // T3: Server A:扣减库存=0,创建订单1 // T4: Server B:扣减库存=-1(超卖!),创建订单2 // synchronized只能锁住单机JVM内的线程 // 无法锁住分布式环境的多个进程 核心问题:分布式环境下,单机锁无效,需要分布式锁。 ...

2025-11-03 · maneng

Redis实战:分布式锁、消息队列、缓存设计

一、分布式锁:从SETNX到Redlock 1.1 为什么需要分布式锁? 场景:秒杀系统的超卖问题 // ❌ 错误:单机锁无法解决分布式超卖 @Service public class SeckillService { @Autowired private ProductRepository productRepository; /** * 秒杀下单(单机锁) */ public synchronized Order seckill(Long productId, Long userId) { // 1. 检查库存 Integer stock = productRepository.getStock(productId); if (stock <= 0) { throw new SoldOutException("商品已售罄"); } // 2. 扣减库存 productRepository.decrementStock(productId); // 3. 创建订单 return orderService.createOrder(productId, userId); } } // 问题: // 假设有3台服务器(Server A、B、C) // T1: Server A:检查库存=1(通过) // T2: Server B:检查库存=1(通过) // T3: Server A:扣减库存=0,创建订单1 // T4: Server B:扣减库存=-1(超卖!),创建订单2 // synchronized只能锁住单机JVM内的线程 // 无法锁住分布式环境的多个进程 核心问题:分布式环境下,单机锁无效,需要分布式锁。 ...

2025-11-03 · maneng

List类型详解:从队列到时间线

引言 在前面我们学习了String和Hash,它们都是"单值"类型。今天我们要学习第一个"集合"类型:List。 List最大的特点是:有序、可重复、双端操作。 想象一下这些场景: 📝 微信朋友圈:按时间倒序展示,最新的在最前面 📮 消息队列:先进先出(FIFO),生产者推送,消费者弹出 📰 最新文章列表:保留最新的100篇,自动淘汰旧的 ⏱️ 操作日志:记录用户最近的操作历史 这些场景的共同特点是:需要保持顺序,支持两端操作。List正是为此而生。 一、List的本质 1.1 什么是List? List是一个双向链表(Doubly Linked List): head tail ↓ ↓ [A] ⇄ [B] ⇄ [C] ⇄ [D] ⇄ [E] ↑ ↑ 左端(head) 右端(tail) LPUSH/LPOP RPUSH/RPOP 特点: ✅ 有序:元素按插入顺序排列 ✅ 可重复:允许重复元素 ✅ 双端操作:可以从左端或右端插入/弹出 ✅ 索引访问:支持按索引读取(但不推荐频繁使用) 1.2 List vs 数组 特性 List(链表) 数组 按索引访问 O(n) O(1) 头尾插入/删除 O(1) O(n) 中间插入/删除 O(n) O(n) 内存占用 较高(指针) 较低 适用场景 队列、栈 随机访问 结论:List适合队列操作,不适合频繁随机访问。 1.3 底层实现 Redis 3.2之前: ...

2025-01-21 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...