0%

文章 《Raft 共识算法学习笔记 一:领导人选举》《Raft 共识算法学习笔记 二:日志复制》 分别讲述了 Raft 算法如何进行领导人选举和如何进行日志复制。

这篇文章继续讲述 Raft 算法如何处理集群成员节点变更的问题。

考虑一种场景,原来 Raft 集群中存在三个节点,现在需要增加2 个节点。那么,在这种情况下, Raft 算法如何能保证同一个任期内,只有一个领导者呢?

Raft 论文中,作者使用配置(configuration)来表示集群由哪些节点组合,即集群所有节点的信息集合。在稳定状态下,所有节点的配置都是一致的。

由于集群存在多个节点,因此,一次性原子地更新所有节点的配置是不可能的,集群在更新配置的过程中,可能会出现新旧配置的两个大多数:

阅读全文 »

文章 Raft 共识算法学习笔记 一:领导人选举 描述了 Raft 算法如何进行领导者选举,本文描述 Raft 共识算法如何进行日志复制。

复制状态机

在 Raft 集群中,每个服务器可以看成是一个复制状态机(Replicated State Machine),如下图。
复制状态机通常基于复制日志(replicated log)实现。每个服务器存储一个包含一系列指令的日志,并且按顺序执行指令。由于日志都包含相同顺序的指令,状态机会按照相同的顺序执行指令,由于状态机是确定的(deterministic),因此状态机会产生相同的结果。
保持这些日志的一致性(consistent)正是共识(consensus)算法的工作。

图:复制状态机工作过程:1. 客户端请求;2. 共识模块执行共识算法进行日志复制,将日志复制至集群内各个节点;3. 日志应用到状态机;4. 服务端返回请求结果

在 Raft 中,指令以日志形式进行复制。集群内只有领导者才能接收客户端请求,其他所有节点都接收来自领导者的复制日志,以达到所有节点日志的一致,并最终达到状态的一致。

Raft 日志

阅读全文 »

Raft 算法是现在分布式系统开发首选的共识算法。文章 《图解 Paxos 算法》 介绍了 Paxos 共识算法,绝大多数选用 Paxos 算法的系统(比如 Cubby),都是在 Raft 算法发布前开发的,当时没得选。新系统绝大多数选择了 Raft 算法,例如,Etcd,Consul,等。就像作者 Diego Ongaro 在 Raft 论文 In Search of an Understandable Consensus Algorithm 说的,Paxos 太难理解了,无论是对于学生还是系统开发者来说,因此 Diego Ongaro 提出了易于理解和实现的 Raft 算法。

本文讲述 Raft 算法如何进行领导者选举。

节点状态

在 Raft 中,节点有以下三种状态:

  • leader(领导者):接收 client (客户端)的所有请求,霸道总裁,一切以我为准。领导者平常的工作包括 3 个部分:处理写请求,管理日志复制,不断发送心跳信息通知其他节点”我是领导者,我还活者,你们现在不要发起新的选举“。Raft 保证任何时刻只有一个 leader
  • follower(跟随者):相当于普通群众,被动接收和处理来自领导者的消息。当领导者心跳超时时,就主动站出来,推荐自己当选候选人
  • candidate(候选人):用于选举出一个新的 leader。候选人向其他节点发送投票 (RequestVote,参考下文 Raft RPX 通信的描述)RPC 消息,通知其他节点来投票,如果赢得子大多数选票,就升级为领导者

节点状态转换示意图如下图所示:

阅读全文 »

Paxos 算法由 Leslie Lamport 在 1989 年提出的一个分布式共识算法,Paxos 算法较难理解,本文尝试以图形化方案解释 Paxos 算法。

本文在很大篇幅参考了韩健极客时间的课程《分布式协议与算法》,有兴趣了解韩老师其他课程的同学可以购买来学习下。

Lamport 提出的 Paxos 算法包括两个部分:

  • Basic Paxos 算法:多节点如何就某个值达成共识
  • Multi Paxos 思想:执行多个 Basic Paxos ,就一系列的值达成共识

Basic Paxos

问题

假设一个集群包含三个节点 A, B, C,提供只读 key-value 存储服务。只读 key-value 的意思是指,当一个 key 被创建时,它的值就确定下来了,且后面不能修改。

客户端 1 和客户端 2 同时试图创建一个 X 键。客户端 1 创建值为 "leehao.me"X ,客户端 2 创建值为 "www.leehao.me"X。在这种情况下,集群如何达成共识,实现各节点上 X 的值一致呢?

阅读全文 »

Spring Cloud 在最新版本 2020.0.0 开始,已去除了 Zuul 网关的使用,改用 Spring Cloud Gateway 作为网关。

Spring Cloud Gateway 基于 Spring WebFlux 框架实现,相对于 Zuul 来说,性能更高。

本文讲述如何在 Spring Cloud 中使用 Nacos 作为注册中心,通过 Spring Cloud Gateway 实现 API 路由的功能。

启动 Nacos

由于需要使用 Nacos 作为注册中心,网关和微服务都注册到 Nacos,因此,需要先启动一个单机版本的 Nacos。

可以参考 Nacos 官方文档 https://nacos.io/zh-cn/docs/quick-start.html 启动一个单机版本的 Nacos。启动成功后,可以通过地址 http://localhost:8868/nacos 访问,用户名 nacos,密码 nacos

启动 Gateway

在 Spring Cloud 项目 springcloudstudy 基础上创建一个 Spring Boot 子项目(有关如何在 IntelliJ Idea 创建 Spring Boot 子项目,可参考 Spring Cloud 使用 Nacos 作配置中心),添加pom.xml 依赖:

1
2
3
4
5
6
7
8
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  • spring-cloud-starter-alibaba-nacos-discovery:使用 Nacos 作为注册中心,需要连接上 Nacos
  • spring-cloud-starter-gateway:使用 Spring Cloud Gateway 作为网关
阅读全文 »

最近公司某项目计划对数据库进行水平分库处理,因此需要实现程序根据参数自动切换数据库的功能。

本文讲述如何在 Spring Cloud + MyBatis + Druid + Oracle 环境下实现动态数据源切换的功能。

配置数据源

在两个 Oracle 数据库创建 Person 表,并插入几行数据:

1
2
3
4
5
6
7
8
9
create table Person
(
id NUMBER(8) not null,
name VARCHAR2(64) not null
)

INSERT INTO Person (id, name) VALUES (1, 'Leo');
INSERT INTO Person (id, name) VALUES (2, 'Lee');
INSERT INTO Person (id, name) VALUES (3, 'Lih');

为便于标识不同数据库的数据,可以将第三行 insert 语句改为:

1
INSERT INTO Person (id, name) VALUES (3, 'LeoLee');

创建一个 Spring Boot 项目,其 application.yml 文件添加两个 Oracle 库的连接信息:

阅读全文 »

文章 《Spring Cloud 使用 Nacos 作配置中心》 描述了如何在 Spring Cloud 使用 Nacos 作配置中心的使用方法,本文在此基础上,使用 Nacos 作为 Spring Cloud 的注册中心。

安装 Nacos

为简单起见,这里使用单机版本的 Nacos Server 作为注册中心,安装过程可以参考 《Spring Cloud 使用 Nacos 作配置中心》

服务提供者

服务提供者在文章 《Spring Cloud 使用 Nacos 作配置中心》 源代码 springcloudstudy 基础上进行开发。其中,springcloudstudy 作为父项目,服务提供者 nacosprovider 作为子项目。

添加 nacosprovider 的依赖:

1
2
3
4
5
6
7
8
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
阅读全文 »

Nacos 是 Spring Cloud Alibaba 核心组件之一,可以用作 Spring Cloud 的注册中心和配置中心。

本文讲述如何在 Spring Cloud 中使用 Nacos 作为配置中心。

安装 Nacos

与 Spring Cloud Config 和 Eureka 的使用方式不同,Nacos Server 需要独立部署。Nacos Server 的部署方式包括单机模式和集群模式,集群模式可以解决 Nacos 高可用的问题。

为简单起见,本文采用单机模式 Nacos Server 作为配置中心。单机模式搭建过程比较简单,可以通过下载源代码编译方式安装和二进制可执行文件安装。

具体安装步骤可以参考官方文档:

https://nacos.io/zh-cn/docs/quick-start.html

安装完成后,使用用户 nacos 和密码 nacos 访问 Nacos 控制台:

图中可以看到访问端口被改成了 8868,而不是 8848。Nacos Server 启动端口的修改也比较简单,修改其配置文件 conf/application.propertie 中端口配置 server.port 即可。

阅读全文 »

阿里巴巴开源的 Druid 是 Java 语言的数据库连接池,提供了强大的监控和扩展功能。

本文讲述如何在 Spring Boot 项目中使用 Druid 数据库连接池。

教程基于文章 《Spring Boot MyBatis 学习教程》 配套的源代码进行扩展,添加 Druid 数据库连接池和监控的功能。如果读者对于 Spring Boot 如何使用 MyBatis 还不了解,可以先完成文章 《Spring Boot MyBatis 学习教程》 的阅读和学习。

添加依赖

pom.xml 文件添加当前最新版本的 Druid 依赖:

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>

形成新的 pom.xml 文件:

阅读全文 »

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL,存储过程以及高级映射。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects)为数据库中的记录。

本文讲述如何在 Spring Boot 框架中基于 XML 方式使用 Mybatis。

创建 MySQL 数据表

本文采用 MySQL 数据库作为数据源,创建用户表 user

1
2
3
4
5
6
7
8
9
CREATE TABLE `user`
(
`id` int(32) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`passwd` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;

插入一行数据:

1
2
insert into user (name, passwd) values ('leo', '123');
commit;

创建 Spring Boot 项目

本文采用 IntelliJ Idea 的 Spring Initializr 向导来创建 Spring Boot 项目,过程比较简单,此处不再赘述。

创建后的 pom.xml 文件如下:

阅读全文 »