本文为分布式系列文章的集锦汇总,长期保持置顶及更新,读者可以在本文中更好的学习到某个具体的系列。

我说分布式事务系列

文章链接
我说分布式事务之TCC
我说分布式事务之最大努力通知型事务
我说分布式事务之可靠消息最终一致性事务1-原理及实现
我说分布式事务之消息一致性事务2-rocketmq的实现
【汇总】我说分布式事务系列
分布式事务之聊聊TCC
分布式事务最终一致性常用方案

跟我学RocketMQ

文章链接
[1-1]安装RocketMQ
[1-2]安装RocketMQ-Console管理平台
[1-3]发送普通消息及封装DefaultMQProducer支持spring
[1-4]消费消息及封装DefaultMQPushConsumer支持spring
[1-5]发送事务消息实现分布式事务及封装TransactionMQProducer支持spring
[1-6]跟我学RocketMQ之消息重试
[1-7]跟我学RocketMQ之消息幂等
[1-8]跟我学RocketMQ之消息轨迹实战与源码分析

分库分表

文章链接
我说分布式之分库分表
跟我学shardingjdbc之shardingjdbc入门
跟我学shardingjdbc之使用jasypt加密数据库连接密码
跟我学shardingjdbc之分布式主键及其自定义
跟我学shardingjdbc之自定义分库分表策略-复合分片算法自定义实现

Read More

RocketMQ在4.4.0 Release版本中支持了消息轨迹特性。

这一特性的增加能够让我们对消息从生产到存储到消费这一整个流程有一个清晰的掌握,配合上console1.0.1以上版本的图形化界面,对于错误排查及日常运维是一个很有用处的feature。

话不多说,我们先通过实战对消息轨迹特性做一次直观的了解,再从源码角度深入分析一下RocketMQ是如何实现消息轨迹这一能力的。

消息轨迹实战

消息轨迹特性在4.4.0时已经支持,本次实战使用最新的4.5.1Release,读者可以自行选择喜欢的版本进行测试。

关于如何搭建并启动RocketMQ集群在本文中不作为重点讲解,感兴趣的同学可以移步 跟我学RocketMQ[1-1]之安装RocketMQ

消息轨迹–broker

RocketMQ对于消息轨迹特性是支持可配置的,如果我们要开启消息轨迹能力,需要编辑broker的配置文件broker.conf,在其中添加如下配置:

traceTopicEnable=true

我们也能够指定自定义的traceTopic名称,具体配置项如下:

msgTraceTopicName=SNOWALKER_TRACE_TOPIC

启动broker会调用相关逻辑自动创建轨迹Topic,如果msgTraceTopicName没有配置则会使用默认值:RMQ_SYS_TRACE_TOPIC

通过Topic实现各种特性是RocketMQ设计精妙之处,定时消息、事务消息、消息重试,包括我们今天接触到的消息轨迹都是这种思想的体现。至于它们具体是如何实现的,我们在文章的后半段的源码分析部分详细展开。

Read More

说罢秒杀网关相关的核心要点,我们接着聊聊秒杀收单相关的核心要点与代码实现。

本文重点说明以下几点:

  1. 业务场景概述
  2. 通过消息队列异步收单
  3. 实际库存扣减
  4. 实际下单操作

业务场景概述

首先对业务场景进行概述。

完整的业务流可参考 实战分布式之电商高并发秒杀场景总览

秒杀收单核心业务逻辑如下:

  1. 秒杀下单消费者从MQ中获取到下单消息,开始下单操作
  2. 首先进行下单前的消息幂等校验,对于已经存在的下单消息不予消费
  3. 接着进行真实的库存判断,如果库存不够扣减则不再消费,这里应当通过消息推送告知用户商品已售罄,提示用户下次再来
  4. 如果库存足够,则扣减库存并下单。这两者在同一个本地事务域中,保证扣减完库存一定能够下单成功
  5. 下单成功后,通过消息推送通知用户对秒杀订单进行付款,付款后进行后续的发货等操作

Read More

从本文开始就进入到了秒杀场景的实现环节,我将主要分两大块进行逐一解析,分别为:

  • 高并发秒杀网关核心要点及代码实现
  • 高并发秒杀收单平台核心要点及代码实现

本篇主要讲一下秒杀网关的要点及编码。

秒杀网关业务场景概述

首先对秒杀网关的主要业务逻辑进行详细的说明。

  1. 秒杀服务网关在启动时对商品、库存、其他配置进行预加载
  2. 用户通过H5/小程序/APP等终端发起秒杀请求,将秒杀下单请求发送至秒杀服务网关
  3. 网关收单接口对用户下单请求进行前置预校验,包括
    1. 参数合法性校验
    2. 商品合法性校验,主要校验下单产品id对应的商品是否存在
    3. 进行商品库存校验,即当前库存是否大于0(或者大于等于1)
    4. 对商品库存进行预减,判断预减库存结果是否大于等于0
  4. 第2步通过后,对收单参数进行处理,组装为秒杀下单消息协议,将消息投递到RocketMQ中
  5. 为用户同步返回 “秒杀请求已接收,排队中”
  6. 上述步骤1-4一旦有处理失败或者校验失败的情况都同步返回用户 “秒杀下单失败”

Read More

纸上得来终觉浅,绝知此事要躬行。–陆游

本文是新系列“实战高并发”的开篇作。这个系列作为“我说分布式”的子系列,将着重挑选若干典型的分布式实战场景,尽量对当下高并发领域较为热门的架构及业务场景做一次较为深入的实践与总结。

该系列既是对笔者接触过的业务的整理,也希望系列中分享的套路能够对读者朋友解决实际业务中面临的问题有所帮助。

言归正传,本文我将主要从业务场景及技术架构等方面出发,对”电商高并发秒杀”这一业务场景做一次较为全面的阐述,同时作为后续实操的开发设计依据。

何为“秒杀”及其特点

“秒杀”这一业务场景在如今已经不是什么新鲜名词,它本质上属于短时突发性高并发访问问题,业务特点如下:

  1. 定时触发,流量在瞬间突增
  2. 秒杀请求中常常只有部分能够成功
  3. 秒杀商品数量往往有限,不能超卖,但能接受少卖
  4. 不要求立即返回真实下单结果

Read More

最近在忙RocketMQ社区的线下开发者训练营的事情,需要准备一个实战课题的demo。

考虑到现场的环境复杂,比如:网络信号不一定很好,每个学员的机器环境不完全一致。因此我决定尽量减少外部组件的依赖,能用内置的就用内置:

缓存不使用Redis,而是用ConcurrentHashMap;数据库不用MySQL了,改用H2嵌入式数据库。

本文就重点整理一下H2嵌入式数据库的整合过程。

Read More

本文是“研磨Kafka”系列较为重要的一篇,我将在本文中重点讲解Kafka是通过何种手段达到消息不丢失的目的。

Kafka通过ISR机制保证了消息发送的可靠性。

首先介绍下什么是ISR。

ISR

ISR,即:in-sync replica,中文含义为:与leader 副本保持同步的副本集合。

我们在之前的文章中已经介绍过Kafka的副本机制,如:单个分区可配置多个副本。

在Kafka中,分区下维护了一个replica集合,集合中所有副本保存的日志都和leader 副本保持着同步状态。

只有该集合中的replica才能被选举为leader,当该集合中所有的副本都收到了同一条消息,Kafka才会将该消息状态设置为“已提交”状态,对客户端而言就是消息发送成功了。

Kafka保证,在分区下的replica集合中,只要存在至少一个replica,则状态为 “已提交” 的消息就不会丢失。

这里我们要记住两个要点:

  1. ISR 中存在至少一个可用的replica
  2. 消息状态为– 已提交

Read More

本文中主要涉及到Kafka的消息主题(Topic)、分区(Partition)、消息位移(Offset)。

主题(Topic)与分区(Partition)

首先说说Topic。

直观的说,Topic是一个逻辑上的概念,代表了一类消息。在业务上,一个Topic代表了一类型的具体的业务场景,如:下单场景使用OrderChargeTopic,支付场景则使用PayOrderTopic。

一个Topic通常会被多个消费者所订阅,从性能方面考量,Kafka没有采用topic->message的两级结构,而是采用了topic->Partition->message三级结构进行负载的分散。也就是说,对于一个topic而言,它包含了多个Partition,对于Partition,我们在 《研磨消息中间件kafka之消息持久化及副本》 这篇文章中也有所涉及。

如图,是Kafka官网对topic与Partition关系的直观表述

topic与Partition

Read More

之前的文章中我们了解了Kafka的消息持久化及副本相关的策略,本文我们学习一下Kafka在高可用方面实现的技术方案。

Kafka在高可用方面主要包含如下的机制:

  1. 负载均衡与故障转移
  2. 伸缩性

我们对这两方面做详细的讲解。

负载均衡与故障转移

首先谈谈Kafka负载均衡的实现机理。

Kafka集群在默认情况相爱,每台服务器都有均等的机会为客户端提供服务,能够将负载分散在集群中的所有机器上,避免了某个节点资源被耗尽的情况出现。

Kafka实现负载均衡本质上是通过分区leader选举实现的,Kafka实现了一套智能的leader选举算法,可以保证集群内所有的机器都能以均等的机会分散各个分区(Partition)的leader,在整体上实现了负载均衡。

接着讨论一下负载均衡的实现。

故障转移,顾名思义,就是在服务器出现故障的时候,集群能够高效的检测到该failure,并立刻将该服务器上的服务自动转移到其他正常的服务节点上。

一般情况下,故障转移是通过“心跳”或者“会话”机制来实现的,也就是当主服务器与备份服务器之间的心跳无法维持或者主服务器注册到服务中心的会话超时过期了,我们就认为主服务器此时已经down掉,集群需要自动的启动某个备份服务器替代down机的主服务器提供服务。

对Kafka而言,故障转移采用的机制是会话机制。

每一个Kafka服务器启动后都会用会话将自己注册到zookeeper上,当它出现故障,与zk之间的会话维持不了导致超时,则Kafka集群会再选取另外一台服务器代替该服务器继续提供服务。

伸缩性

如果服务需要具备伸缩性,那很大程度上表明该服务本身是无状态的,而Kafka服务器正是利用了无状态的思想,将状态的保存与管理交给分布式协调服务zookeeper来做,服务器本身便不需要做复杂的状态保持,降低了维护的复杂度。

因为服务本身无状态,因此可以通过增减节点达到集群的扩缩容。

当然Kafka本身并不是什么状态都不保持,它也保留了一部分必要的内部状态。

本文主要介绍Kafka的消息持久化策略及副本机制。

Kafka消息持久化策略

首先简要说明一下Kafka持久化消息的优点:

  1. Kafka通过消息持久化解耦了消息的生产者和消费者,这也是采用队列的优势,使得生产者和消费者均只需要关心自己的逻辑,而不需要直接感知到彼此的存在。
  2. Kafka支持对消费过的消息进行“消息重演(Message Replay)”,而重演的基础就是实现消息持久化。

Kafka为了保证消息落盘的实时,确保消息不丢失,没有采用直接写内存,等写满后一次性刷盘的策略,而是将数据立即写入文件系统的日志中,写入成功后才将结果返回给客户端告知客户端–消息已经成功写入。这么做的目的是,一方面实时地保存了数据,另一方面又减少了对内存的消耗,将内存空间尽量留给页缓存使用,从而提升了整体的性能。

Read More

Fork me on GitHub