本文是新系列“研磨”系列的开篇,该系列主要立足源码分析、核心技术点分析、常见问题整理等方面。一篇文章围绕一个中间件,立足于讲清、讲透、讲明白。

系列的第一部分主题为–“研磨Kafka”,本篇中,我们先从宏观的视角窥探Kafka的核心角色,并对后文中要讲到的主题做一个宏观的概述。

Kafka的设计原理及结构概述

首先对Kafka重要的角色进行总结。

要点 解释
Kafka概述 Kafka是一款分布式消息中间件,但它不符合JMS规范。
消费特点 Kafka消费消息成功,不会马上删除消息。消息存储一段时间后,会被批量删除。
Broker Broker是Kafka的服务端,主要作用为接收消息并对消息进行持久化存储。
Broker可以有多个,每一个Broker节点可存储多个Topic。但是Broker本身并不会存储消费的Offset(即消费者消费消息的位置),Offset数据由Consumer(消费者)保存,保存位置为Zookeeper。
Topic Topic为消息主题,它是生产者与消费者之间进行消息传递的依据。单个Topic下包括多个Partition,它的所有元数据存储在zookeeper中。
Partition Partition即分区,Kafka为提高性能及扩展性,将一个Topic分为多个分区,及Partition,每个Partition均可独立存放在一个Broker上,这保证了Kafka的可用性及稳定性。
Producer Producer为消息生产者,它一般是集成了Kafka客户端的业务应用。
Producer负责发送消息到Broker。Producer直连Broker,具有往Topic下发布消息的能力。
它会与Topic下的所有PartitionLeader保持Socket长连接。Producer具有同步、异步两种消息发送能力,且Producer支持消息的批量发送,即将多条消息缓存在客户端,在达到指定的时间延迟或者消息数量后,批量地提交给Broker。
Consumer Consumer为消息消费者,它一般是集成了Kafka客户端的业务应用。消费者向Broker订阅Topic,并从Topic中接收消息。
每一个消费者均属于某一个消费者组,且同消费者组中的消费者订阅同一个Topic,同一个Topic下的不同消费者分别订阅该Topic下不同Partition的数据。一个消费者可以订阅多个Partition,但同一个Partition只能被一个消费者订阅,该策略的目的是一定程度上避免消息被重复消费。
可以通过增加Partition的方式对消费能力进行横向扩展。
当出现某个消费者down机,消费过程会进行 Rebalance

研磨Kafka主题

该系列后续会涉及到的要点,在此处进行整理

要点
如何提升Kafka的吞吐量及低延时
Kafka的消息持久化方式
Kafka如何实现负载均衡及故障转移
如何理解Kafka的“伸缩性”特点
概览主题(Topic)与分区(Partition)
解释什么是消息位移offset
解释下Kafka的副本机制如何实现
Kafka如何利用“ISR机制”保证消息不丢失?
kafka是否存在消息丢失的情况?

Kafka使用场景

Kafka主要应用的场景如下

场景 说明
消息传递 Kafka的高吞吐、高可靠特性使得它很适合作为消息总线或者消息代理的替代品,常用来实现超大规模消息引擎集群。
用户行为分析 Kafka在大数据领域常常与大数据组件相结合,协助进行用户行为数据的搜集。
运维数据收集 在运维领域,Kafka常被用作异步数据上报,监控数据收集等场景。
日志收集 这是Kafka使用的经典场景,通过Kafka对分散在不同机器上的机器进行收集,并集中存储在分布式存储中,Kafka的高吞吐、低延时的特性让它能够成为主流的日志收集解决方案。
流式处理 Kafka社区推出的Kafka Streams标志着它正式进入流式处理的大家庭。

首先了解下何为SPI,这里引用Dubbo官方对SPI的解说,比较全面。SPI简介

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。

Dubbo本身实现了对JDK的SPI的扩展,为了能够更好的理解Dubbo的SPI机制,我们需要理解JDK的原生SPI原理。

从概念可以看出,SPI机制是一种服务发现机制,能够在运行时动态的增加、获取服务实现。个人感觉很像设计原则中的里氏替换原则。

我将通过一个实例来讲解如何对JDK的SPI进行运用。

Read More

考虑到部分业务场景下没有使用RocketMQ,因此我在之前的基础上添加了对单机模式调度的封装。

本文就单机模式下,不依赖RocketMQ如何使用shield-job进行定时任务调度展开讲解。

目前有两种主要的调用方式,客户端实现抽象调度方法 execute ,或者直接使用内置的 executeOneway 方法进行调用,接下来分别介绍两种方式。

Read More

自己写分布式调度组件继续更新,目前已经完成了一个里程碑版本。

千呼万唤始出来,却不是当初想的模样。之前立的flag太大,最终决定暂时放弃开发分布式版本,把目标改为基于消息队列RocketMQ的任务分发框架,具体的调度逻辑由调用方自行开发。

客户端接口

首先介绍客户端需要关注的接口以及实体

客户端实体–任务实体BaseJob

任务实体BaseJob为shield-job的调度核心实体,调用方的业务实体需要继承该作业抽象类,实现其中的encode() 以及 decode(String msg) 抽象方法。

Read More

在上篇中,我们了解了RocketMQ中的消息重试机制以及如何在Producer、Consumer两端对重试消息进行处理。

RocketMQ会在消息消费时,按照一定规则推送消息到消费者端进行消息重试。这里涉及到了消息幂等的概念。

首先我们了解一下什么是幂等,以及何为消息幂等。

什么是幂等

百度对 “幂等” 解释如下

设f为一由X映射至X的一元运算,则f为幂等的,当对于所有在X内的x,
f(f(x)) = f(x).
特别的是,恒等函数一定是幂等的,且任一常数函数也都是幂等的。

这里的关键是 f(f(x)) = f(x), 翻译成通俗的解释就是:

如果有一个操作,多次执行与一次执行所产生的影响是相同的,我们就称这个操作是幂等的。

关于消息幂等

基于上述的概念,结合消息消费的场景,我们能够很容易的总结出消息幂等的概念:

即:

如果消息重试多次,消费者端对该重复消息消费多次与消费一次的结果是相同的,并且多次消费没有对系统产生副作用,那么我们就称这个过程是消息幂等的。

例如:

支付场景下,消费者消费扣款消息,对一笔订单进行扣款操作,该扣款操作需要扣除10元。

这个扣款操作重复多次与执行一次的效果相同,只进行一次真实扣款,用户的扣款记录中对应该笔订单的只有一条扣款流水。不会多扣。那么我们就说这个扣款操作是符合要求的,这个消费过程是消息幂等的。

Read More

本文中,我将讲解RocketMQ使用过程中,如何进行消息重试。

首先,我们需要明确,只有当消费模式为 MessageModel.CLUSTERING(集群模式) 时,Broker才会自动进行重试,对于广播消息是不会重试的。

集群消费模式下,当消息消费失败,RocketMQ会通过消息重试机制重新投递消息,努力使该消息消费成功。

当消费者消费该重试消息后,需要返回结果给broker,告知broker消费成功(ConsumeConcurrentlyStatus.CONSUME_SUCCESS)或者需要重新消费(ConsumeConcurrentlyStatus.RECONSUME_LATER)。

这里有个问题,如果消费者业务本身故障导致某条消息一直无法消费成功,难道要一直重试下去吗?

答案是显而易见的,并不会一直重试。

事实上,对于一直无法消费成功的消息,RocketMQ会在达到最大重试次数之后,将该消息投递至死信队列。然后我们需要关注死信队列,并对该死信消息业务做人工的补偿操作。

Read More

本文是 “跟我学Sharding-JDBC” 系列的第四篇,我将带领读者一起了解下Sharding-JDBC的数据分片规则并通过实例实现自定义分片策略的开发实现。

Sharding-JDBC中的分片策略有两个维度,分别是:数据源分片策略(DatabaseShardingStrategy)、表分片策略(TableShardingStrategy)。

其中,数据源分片策略表示:数据路由到的物理目标数据源,表分片策略表示数据被路由到的目标表。

特别的,表分片策略是依赖于数据源分片策略的,也就是说要先分库再分表。

这里贴一张盗来的图

Sharding-JDBC分片策略代码架构

Read More

本文是 “跟我学Sharding-JDBC” 系列的第三篇,我将带领读者一起了解下Sharding-JDBC的分布式主键,并实现业务性更强的自定义主键。

首先了解下,什么是分布式主键。

传统的关系型数据库,如MySQL中,数据库本身自带自增主键生成机制,但在分布式环境下,由于分库分表导致数据水平拆分后无法使用单表自增主键,因此我们需要一种全局唯一id生成策略作为分布式主键。

当前业界已经有不少成熟的方案能够解决分布式主键的生成问题,如:UUID、SnoWflake算法(Twitter)、Leaf算法(美团点评)等。

Read More

“云计算”的概念从提出到现在已经过了十多年,经过了大量的实践之后早已不再是阳春白雪般不接地气的抽象理论。

随着微服务的提出到落地,分布式领域中又诞生了新的基于云的理论–“云原生(Cloud Native)”。

“云原生”的概念由来自Pivotal的Matt Stine于2013年首次提出,被一直延续使用至今……(它涵盖的)内容非常多,包括DevOps持续交付微服务敏捷基础设施以及12要素等几大主题。不但包括根据业务能力对公司进行文化、组织架构的重组与建设,也包括方法论与原则,还有具体的操作工具。 –《云原生技术架构实践》

本文,我将主要介绍云原生的12要素,并着重讲解云原生中关于微服务的主题中的容器化与应用无状态的特性。

Read More

Fork me on GitHub