auto commit
This commit is contained in:
parent
832cf4086e
commit
2556c103ab
103
notes/分布式问题分析.md
103
notes/分布式问题分析.md
|
@ -4,33 +4,16 @@
|
||||||
* [1. 产生原因](#1-产生原因)
|
* [1. 产生原因](#1-产生原因)
|
||||||
* [2. 应用场景](#2-应用场景)
|
* [2. 应用场景](#2-应用场景)
|
||||||
* [3. 解决方案](#3-解决方案)
|
* [3. 解决方案](#3-解决方案)
|
||||||
* [3.1 两阶段提交协议](#31-两阶段提交协议)
|
|
||||||
* [3.2 消息中间件](#32-消息中间件)
|
|
||||||
* [负载均衡的算法与实现](#负载均衡的算法与实现)
|
* [负载均衡的算法与实现](#负载均衡的算法与实现)
|
||||||
* [1. 算法](#1-算法)
|
* [1. 算法](#1-算法)
|
||||||
* [1.1 轮询(Round Robin)](#11-轮询round-robin)
|
|
||||||
* [1.2 加权轮询(Weighted Round Robbin)](#12-加权轮询weighted-round-robbin)
|
|
||||||
* [1.3 最少连接(least Connections)](#13-最少连接least-connections)
|
|
||||||
* [1.4 加权最小连接(Weighted Least Connection)](#14-加权最小连接weighted-least-connection)
|
|
||||||
* [1.5 随机算法(Random)](#15-随机算法random)
|
|
||||||
* [2. 实现](#2-实现)
|
* [2. 实现](#2-实现)
|
||||||
* [2.1 DNS 解析](#21-dns-解析)
|
|
||||||
* [2.2 修改 MAC 地址](#22-修改-mac-地址)
|
|
||||||
* [2.3 修改 IP 地址](#23-修改-ip-地址)
|
|
||||||
* [2.4 HTTP 重定向](#24-http-重定向)
|
|
||||||
* [2.5 反向代理](#25-反向代理)
|
|
||||||
* [分布式锁](#分布式锁)
|
* [分布式锁](#分布式锁)
|
||||||
* [1. 使用场景](#1-使用场景)
|
* [1. 使用场景](#1-使用场景)
|
||||||
* [2. 实现方式](#2-实现方式)
|
* [2. 实现方式](#2-实现方式)
|
||||||
* [2.1 数据库分布式锁](#21-数据库分布式锁)
|
|
||||||
* [2.2 Redis 分布式锁](#22-redis-分布式锁)
|
|
||||||
* [2.3 Zookeeper 分布式锁](#23-zookeeper-分布式锁)
|
|
||||||
* [分布式 Session](#分布式-session)
|
* [分布式 Session](#分布式-session)
|
||||||
* [1. 粘性 Session](#1-粘性-session)
|
* [1. 粘性 Session](#1-粘性-session)
|
||||||
* [2. 服务器 Session 复制](#2-服务器-session-复制)
|
* [2. 服务器 Session 复制](#2-服务器-session-复制)
|
||||||
* [3. Session 共享机制](#3-session-共享机制)
|
* [3. Session 共享机制](#3-session-共享机制)
|
||||||
* [3.1 粘性 Session 共享机制](#31-粘性-session-共享机制)
|
|
||||||
* [3.2 非粘性 Session 共享机制](#32-非粘性-session-共享机制)
|
|
||||||
* [4. Session 持久化到数据库](#4-session-持久化到数据库)
|
* [4. Session 持久化到数据库](#4-session-持久化到数据库)
|
||||||
* [5. Terracotta 实现 Session 复制](#5-terracotta-实现-session-复制)
|
* [5. Terracotta 实现 Session 复制](#5-terracotta-实现-session-复制)
|
||||||
* [分库与分表带来的分布式困境与应对之策](#分库与分表带来的分布式困境与应对之策)
|
* [分库与分表带来的分布式困境与应对之策](#分库与分表带来的分布式困境与应对之策)
|
||||||
|
@ -43,15 +26,15 @@
|
||||||
|
|
||||||
# 谈谈业务中使用分布式的场景
|
# 谈谈业务中使用分布式的场景
|
||||||
|
|
||||||
分布式主要是为了提供可扩展性以及高可用性,业务中使用分布式的场景主要有分布式数据库以及分布式计算。
|
分布式主要是为了提供可扩展性以及高可用性,业务中使用分布式的场景主要有分布式存储以及分布式计算。
|
||||||
|
|
||||||
例如分布式数据库中可以将数据分片到多台机器上,不仅可以降低一台机器的压力,同时也可以使用多台机器对一份数据进行备份。
|
分布式存储中可以将数据分片到多个节点上,不仅可以提高性能(可扩展性),同时也可以使用多个节点对同一份数据进行备份。
|
||||||
|
|
||||||
至于分布式计算,就是将一个大的计算任务分解成小任务分配到多台机器上去执行,然后再汇总每个小任务的执行结果得到最终结果。MapReduce 是分布式计算的最好例子。
|
至于分布式计算,就是将一个大的计算任务分解成小任务分配到多台节点上去执行,再汇总每个小任务的执行结果得到最终结果。MapReduce 是分布式计算的最好例子。
|
||||||
|
|
||||||
# 分布式事务
|
# 分布式事务
|
||||||
|
|
||||||
指事务的每个操作步骤都位于不同的节点上,需要保证事务的 AICD 特性。
|
指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。
|
||||||
|
|
||||||
## 1. 产生原因
|
## 1. 产生原因
|
||||||
|
|
||||||
|
@ -60,26 +43,28 @@
|
||||||
|
|
||||||
## 2. 应用场景
|
## 2. 应用场景
|
||||||
|
|
||||||
- 下单:减少库存同时更新订单状态。库存和订单不在不同一个数据库,因此涉及分布式事务。
|
- 下单:减少库存、更新订单状态。库存和订单不在不同一个数据库,因此涉及分布式事务。
|
||||||
- 支付:买家账户扣款同时卖家账户入账。买家和卖家账户信息不在同一个数据库,因此涉及分布式事务。
|
- 支付:买家账户扣款、卖家账户入账。买家和卖家账户信息不在同一个数据库,因此涉及分布式事务。
|
||||||
|
|
||||||
## 3. 解决方案
|
## 3. 解决方案
|
||||||
|
|
||||||
### 3.1 两阶段提交协议
|
### 3.1 两阶段提交协议
|
||||||
|
|
||||||
两阶段提交协议可以很好得解决分布式事务问题,它可以使用 XA 来实现,XA 它包含两个部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如 Oracle、DB2 这些商业数据库都实现了 XA 接口,而事务管理器作为全局的协调者,负责各个本地资源的提交和回滚。
|
[两阶段提交](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E4%B8%80%E8%87%B4%E6%80%A7%E5%8D%8F%E8%AE%AE.md#%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4%E5%8D%8F%E8%AE%AE)
|
||||||
|
|
||||||
|
两阶段提交协议可以很好得解决分布式事务问题,它可以使用 XA 来实现,XA 它包含两个部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如 Oracle、DB2 这些商业数据库都实现了 XA 接口;而事务管理器作为全局的协调者,负责各个本地资源的提交和回滚。
|
||||||
|
|
||||||
### 3.2 消息中间件
|
### 3.2 消息中间件
|
||||||
|
|
||||||
消息中间件也可称作消息系统 (MQ),它本质上是一个暂存转发消息的一个中间件。在分布式应用当中,我们可以把一个业务操作转换成一个消息,比如支付宝的余额转如余额宝操作,支付宝系统执行减少余额操作之后向消息系统发一个消息,余额宝系统订阅这条消息然后进行增加账户金额操作。
|
消息中间件也可称作消息系统 (MQ),它本质上是一个暂存转发消息的一个中间件。在分布式应用当中,我们可以把一个业务操作转换成一个消息,比如支付宝的余额转入余额宝操作,支付宝系统执行减少余额操作之后向消息系统发送一个消息,余额宝系统订阅这条消息然后进行增加余额宝操作。
|
||||||
|
|
||||||
#### 3.2.1 消息处理模型
|
#### 3.2.1 消息处理模型
|
||||||
|
|
||||||
点对点
|
##### 点对点
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//96b63e13-e2d8-4ddb-9aa1-a38959ca96e5.jpg" width="600"/> </div><br>
|
<div align="center"> <img src="../pics//96b63e13-e2d8-4ddb-9aa1-a38959ca96e5.jpg" width="600"/> </div><br>
|
||||||
|
|
||||||
发布/订阅
|
##### 发布/订阅
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//654acfed-a6a5-4fc7-8f40-3fdcae57bae8.jpg" width="700"/> </div><br>
|
<div align="center"> <img src="../pics//654acfed-a6a5-4fc7-8f40-3fdcae57bae8.jpg" width="700"/> </div><br>
|
||||||
|
|
||||||
|
@ -121,17 +106,17 @@
|
||||||
|
|
||||||
### 1.3 最少连接(least Connections)
|
### 1.3 最少连接(least Connections)
|
||||||
|
|
||||||
由于每个请求的连接时间不一样,使用轮询或者加权轮询算法的话,可能会让一台服务器当前连接数多大,而另一台服务器的连接多小,造成负载不均衡。例如下图中,(1, 3, 5) 请求会被发送到服务器 1,但是 (1, 3) 很快就断开连接,此时只有 (5) 请求连接服务器 1;(2, 4, 6) 请求被发送到服务器 2,它们的连接都还没有断开,继续运行时,服务器 2 会承担多大的负载。
|
由于每个请求的连接时间不一样,使用轮询或者加权轮询算法的话,可能会让一台服务器当前连接数多大,而另一台服务器的连接多小,造成负载不均衡。例如下图中,(1, 3, 5) 请求会被发送到服务器 1,但是 (1, 3) 很快就断开连接,此时只有 (5) 请求连接服务器 1;(2, 4, 6) 请求被发送到服务器 2,只有 (2) 的连接断开。该系统继续运行时,服务器 2 会承担多大的负载。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//3b0d1aa8-d0e0-46c2-8fd1-736bf08a11aa.jpg"/> </div><br>
|
<div align="center"> <img src="../pics//3b0d1aa8-d0e0-46c2-8fd1-736bf08a11aa.jpg"/> </div><br>
|
||||||
|
|
||||||
最少连接算法就是将请求发送给当前最少连接数的服务器上。例如下图中,服务器 1 当前连接数最小,那么请求 6 就会被发送到服务器 1 上。
|
最少连接算法就是将请求发送给当前最少连接数的服务器上。例如下图中,服务器 1 当前连接数最小,那么新到来的请求 6 就会被发送到服务器 1 上。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//1f4a7f10-52b2-4bd7-a67d-a9581d66dc62.jpg"/> </div><br>
|
<div align="center"> <img src="../pics//1f4a7f10-52b2-4bd7-a67d-a9581d66dc62.jpg"/> </div><br>
|
||||||
|
|
||||||
### 1.4 加权最小连接(Weighted Least Connection)
|
### 1.4 加权最小连接(Weighted Least Connection)
|
||||||
|
|
||||||
在最小连接的基础上,根据服务器的性能为每台服务器分配权重,然后根据权重计算出每台服务器能处理的连接数。
|
在最小连接的基础上,根据服务器的性能为每台服务器分配权重,根据权重计算出每台服务器能处理的连接数。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//44edefb7-4b58-4519-b8ee-4aca01697b78.jpg"/> </div><br>
|
<div align="center"> <img src="../pics//44edefb7-4b58-4519-b8ee-4aca01697b78.jpg"/> </div><br>
|
||||||
|
|
||||||
|
@ -145,7 +130,7 @@
|
||||||
|
|
||||||
### 2.1 DNS 解析
|
### 2.1 DNS 解析
|
||||||
|
|
||||||
使用 DNS 作为负载均衡器,会根据负载情况返回不同服务器的 IP 地址。大型网站基本使用了这种方式最为第一级负载均衡手段,然后在内部在第二级负载均衡。
|
使用 DNS 作为负载均衡器,根据负载情况返回不同服务器的 IP 地址。大型网站基本使用了这种方式最为第一级负载均衡手段,然后在内部使用其它方式做第二级负载均衡。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//42e17a80-b9fc-42a2-9ba8-68364fae3710.jpg" width="500"/> </div><br>
|
<div align="center"> <img src="../pics//42e17a80-b9fc-42a2-9ba8-68364fae3710.jpg" width="500"/> </div><br>
|
||||||
|
|
||||||
|
@ -163,7 +148,7 @@
|
||||||
|
|
||||||
### 2.4 HTTP 重定向
|
### 2.4 HTTP 重定向
|
||||||
|
|
||||||
HTTP 重定向负载均衡服务器收到 HTTP 请求之后会返回服务器的地址,并将该地址写入 HTTP 重定向响应中返回给浏览器,浏览器收到后再次发送请求。
|
HTTP 重定向负载均衡服务器收到 HTTP 请求之后会返回服务器的地址,并将该地址写入 HTTP 重定向响应中返回给浏览器,浏览器收到后需要再次发送请求。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//9208563b-014d-4745-aa1c-492c9f7f7a7f.jpg" width="500"/> </div><br>
|
<div align="center"> <img src="../pics//9208563b-014d-4745-aa1c-492c9f7f7a7f.jpg" width="500"/> </div><br>
|
||||||
|
|
||||||
|
@ -171,7 +156,7 @@ HTTP 重定向负载均衡服务器收到 HTTP 请求之后会返回服务器的
|
||||||
|
|
||||||
正向代理:发生在客户端,是由用户主动发起的。比如翻墙,客户端通过主动访问代理服务器,让代理服务器获得需要的外网数据,然后转发回客户端。
|
正向代理:发生在客户端,是由用户主动发起的。比如翻墙,客户端通过主动访问代理服务器,让代理服务器获得需要的外网数据,然后转发回客户端。
|
||||||
|
|
||||||
反向代理:发生在服务器端,用户不知道发生了代理。
|
反向代理:发生在服务器端,用户不知道代理的存在。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//b750eb3e-8a80-475c-95df-2e971b277603.jpg" width="500"/> </div><br>
|
<div align="center"> <img src="../pics//b750eb3e-8a80-475c-95df-2e971b277603.jpg" width="500"/> </div><br>
|
||||||
|
|
||||||
|
@ -187,7 +172,7 @@ Java 提供了两种内置的锁的实现,一种是由 JVM 实现的 synchroni
|
||||||
|
|
||||||
### 2.1 数据库分布式锁
|
### 2.1 数据库分布式锁
|
||||||
|
|
||||||
**基于 MySQL 锁表**
|
#### 基于 MySQL 锁表
|
||||||
|
|
||||||
该实现方式完全依靠数据库唯一索引来实现。当想要获得锁时,就向数据库中插入一条记录,释放锁时就删除这条记录。如果记录具有唯一索引,就不会同时插入同一条记录。这种方式存在以下几个问题:
|
该实现方式完全依靠数据库唯一索引来实现。当想要获得锁时,就向数据库中插入一条记录,释放锁时就删除这条记录。如果记录具有唯一索引,就不会同时插入同一条记录。这种方式存在以下几个问题:
|
||||||
|
|
||||||
|
@ -195,19 +180,19 @@ Java 提供了两种内置的锁的实现,一种是由 JVM 实现的 synchroni
|
||||||
2. 只能是非阻塞锁,插入失败直接就报错了,无法重试。
|
2. 只能是非阻塞锁,插入失败直接就报错了,无法重试。
|
||||||
3. 不可重入,同一线程在没有释放锁之前无法再获得锁。
|
3. 不可重入,同一线程在没有释放锁之前无法再获得锁。
|
||||||
|
|
||||||
**采用乐观锁增加版本号**
|
#### 采用乐观锁增加版本号
|
||||||
|
|
||||||
根据版本号来判断更新之前有没有其他线程更新过,如果被更新过,则获取锁失败。
|
根据版本号来判断更新之前有没有其他线程更新过,如果被更新过,则获取锁失败。
|
||||||
|
|
||||||
### 2.2 Redis 分布式锁
|
### 2.2 Redis 分布式锁
|
||||||
|
|
||||||
**基于 SETNX、EXPIRE**
|
#### 基于 SETNX、EXPIRE
|
||||||
|
|
||||||
使用 SETNX(set if not exist)命令插入一个键值对时,如果 Key 已经存在,那么会返回 False,否则插入成功并返回 True。因此客户端在尝试获得锁时,先使用 SETNX 向 Redis 中插入一个记录,如果返回 True 表示获得锁,返回 False 表示已经有客户端占用锁。
|
使用 SETNX(set if not exist)命令插入一个键值对时,如果 Key 已经存在,那么会返回 False,否则插入成功并返回 True。因此客户端在尝试获得锁时,先使用 SETNX 向 Redis 中插入一个记录,如果返回 True 表示获得锁,返回 False 表示已经有客户端占用锁。
|
||||||
|
|
||||||
EXPIRE 可以为一个键值对设置一个过期时间,从而避免了死锁的发生。
|
EXPIRE 可以为一个键值对设置一个过期时间,从而避免了死锁的发生。
|
||||||
|
|
||||||
**RedLock 算法**
|
#### RedLock 算法
|
||||||
|
|
||||||
ReadLock 算法使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时还可用。
|
ReadLock 算法使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时还可用。
|
||||||
|
|
||||||
|
@ -219,34 +204,34 @@ ReadLock 算法使用了多个 Redis 实例来实现分布式锁,这是为了
|
||||||
|
|
||||||
Zookeeper 是一个为分布式应用提供一致性服务的软件,例如配置管理、分布式协同以及命名的中心化等,这些都是分布式系统中非常底层而且是必不可少的基本功能,但是如果自己实现这些功能而且要达到高吞吐、低延迟同时还要保持一致性和可用性,实际上非常困难。
|
Zookeeper 是一个为分布式应用提供一致性服务的软件,例如配置管理、分布式协同以及命名的中心化等,这些都是分布式系统中非常底层而且是必不可少的基本功能,但是如果自己实现这些功能而且要达到高吞吐、低延迟同时还要保持一致性和可用性,实际上非常困难。
|
||||||
|
|
||||||
**抽象模型**
|
#### 抽象模型
|
||||||
|
|
||||||
Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示它的父节点为 /app1。
|
Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示它的父节点为 /app1。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//31d99967-1171-448e-8531-bccf5c14cffe.jpg" width="400"/> </div><br>
|
<div align="center"> <img src="../pics//31d99967-1171-448e-8531-bccf5c14cffe.jpg" width="400"/> </div><br>
|
||||||
|
|
||||||
**节点类型**
|
#### 节点类型
|
||||||
|
|
||||||
- 永久节点:不会因为会话结束或者超时而消失;
|
- 永久节点:不会因为会话结束或者超时而消失;
|
||||||
- 临时节点:如果会话结束或者超时就会消失;
|
- 临时节点:如果会话结束或者超时就会消失;
|
||||||
- 有序节点:会在节点名的后面加一个数字后缀,并且是有序的,例如生成的有序节点为 /lock/node-0000000000,它的下一个有序节点则为 /lock/node-0000000001,依次类推。
|
- 有序节点:会在节点名的后面加一个数字后缀,并且是有序的,例如生成的有序节点为 /lock/node-0000000000,它的下一个有序节点则为 /lock/node-0000000001,依次类推。
|
||||||
|
|
||||||
**监听器**
|
#### 监听器
|
||||||
|
|
||||||
为一个节点注册监听器,在节点状态发生改变时,会给客户端发送消息。
|
为一个节点注册监听器,在节点状态发生改变时,会给客户端发送消息。
|
||||||
|
|
||||||
**分布式锁实现**
|
#### 分布式锁实现
|
||||||
|
|
||||||
1. 创建一个锁目录 /lock。
|
1. 创建一个锁目录 /lock。
|
||||||
1. 在 /lock 下创建临时的且有序的子节点,第一个客户端对应的子节点为 /lock/lock-0000000000,第二个为 /lock/lock-0000000001,以此类推。
|
1. 在 /lock 下创建临时的且有序的子节点,第一个客户端对应的子节点为 /lock/lock-0000000000,第二个为 /lock/lock-0000000001,以此类推。
|
||||||
2. 客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听自己的前一个子节点,获得子节点的变更通知后重复此步骤直至获得锁;
|
2. 客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听自己的前一个子节点,获得子节点的变更通知后重复此步骤直至获得锁;
|
||||||
3. 执行业务代码,完成后,删除对应的子节点。
|
3. 执行业务代码,完成后,删除对应的子节点。
|
||||||
|
|
||||||
**会话超时**
|
#### 会话超时
|
||||||
|
|
||||||
如果一个已经获得锁的会话超时了,因为创建的是临时节点,因此该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库分布式锁的死锁问题。
|
如果一个已经获得锁的会话超时了,因为创建的是临时节点,因此该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库分布式锁的死锁问题。
|
||||||
|
|
||||||
**羊群效应**
|
#### 羊群效应
|
||||||
|
|
||||||
在步骤二,一个节点未获得锁,需要监听监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知,而我们只希望它的下一个子节点收到通知。
|
在步骤二,一个节点未获得锁,需要监听监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知,而我们只希望它的下一个子节点收到通知。
|
||||||
|
|
||||||
|
@ -256,38 +241,38 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||||
|
|
||||||
## 1. 粘性 Session
|
## 1. 粘性 Session
|
||||||
|
|
||||||
**原理**
|
### 原理
|
||||||
|
|
||||||
粘性 Session 是指将用户锁定到某一个服务器上,比如上面说的例子,用户第一次请求时,负载均衡器将用户的请求转发到了 A 服务器上,如果负载均衡器设置了粘性 Session 的话,那么用户以后的每次请求都会转发到 A 服务器上,相当于把用户和 A 服务器粘到了一块,这就是粘性 Session 机制。
|
粘性 Session 是指将用户锁定到某一个服务器上,比如上面说的例子,用户第一次请求时,负载均衡器将用户的请求转发到了 A 服务器上,如果负载均衡器设置了粘性 Session 的话,那么用户以后的每次请求都会转发到 A 服务器上,相当于把用户和 A 服务器粘到了一块,这就是粘性 Session 机制。
|
||||||
|
|
||||||
**优点**
|
### 优点
|
||||||
|
|
||||||
简单,不需要对 Session 做任何处理。
|
简单,不需要对 Session 做任何处理。
|
||||||
|
|
||||||
**缺点**
|
### 缺点
|
||||||
|
|
||||||
缺乏容错性,如果当前访问的服务器发生故障,用户被转移到第二个服务器上时,他的 Session 信息都将失效。
|
缺乏容错性,如果当前访问的服务器发生故障,用户被转移到第二个服务器上时,他的 Session 信息都将失效。
|
||||||
|
|
||||||
**适用场景**
|
### 适用场景
|
||||||
|
|
||||||
- 发生故障对客户产生的影响较小;
|
- 发生故障对客户产生的影响较小;
|
||||||
- 服务器发生故障是低概率事件。
|
- 服务器发生故障是低概率事件。
|
||||||
|
|
||||||
## 2. 服务器 Session 复制
|
## 2. 服务器 Session 复制
|
||||||
|
|
||||||
**原理**
|
### 原理
|
||||||
|
|
||||||
任何一个服务器上的 Session 发生改变,该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要 Session,以此来保证 Session 同步。
|
任何一个服务器上的 Session 发生改变,该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要 Session,以此来保证 Session 同步。
|
||||||
|
|
||||||
**优点**
|
### 优点
|
||||||
|
|
||||||
可容错,各个服务器间 Session 能够实时响应。
|
可容错,各个服务器间 Session 能够实时响应。
|
||||||
|
|
||||||
**缺点**
|
### 缺点
|
||||||
|
|
||||||
会对网络负荷造成一定压力,如果 Session 量大的话可能会造成网络堵塞,拖慢服务器性能。
|
会对网络负荷造成一定压力,如果 Session 量大的话可能会造成网络堵塞,拖慢服务器性能。
|
||||||
|
|
||||||
**实现方式**
|
### 实现方式
|
||||||
|
|
||||||
1. 设置 Tomcat 的 server.xml 开启 tomcat 集群功能。
|
1. 设置 Tomcat 的 server.xml 开启 tomcat 集群功能。
|
||||||
2. 在应用里增加信息:通知应用当前处于集群环境中,支持分布式,即在 web.xml 中添加<distributable/> 选项。
|
2. 在应用里增加信息:通知应用当前处于集群环境中,支持分布式,即在 web.xml 中添加<distributable/> 选项。
|
||||||
|
@ -306,43 +291,43 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||||
|
|
||||||
### 3.2 非粘性 Session 共享机制
|
### 3.2 非粘性 Session 共享机制
|
||||||
|
|
||||||
**原理**
|
#### 原理
|
||||||
|
|
||||||
Tomcat 本身不存储 Session,而是存入 Memcached 中。Memcached 集群构建主从复制架构。
|
Tomcat 本身不存储 Session,而是存入 Memcached 中。Memcached 集群构建主从复制架构。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//ce0fa5d0-866b-46e6-a873-8eb1f78c2882.jpg" width="400"/> </div><br>
|
<div align="center"> <img src="../pics//ce0fa5d0-866b-46e6-a873-8eb1f78c2882.jpg" width="400"/> </div><br>
|
||||||
|
|
||||||
**优点**
|
#### 优点
|
||||||
|
|
||||||
可容错,Session 实时响应。
|
可容错,Session 实时响应。
|
||||||
|
|
||||||
**实现方式**
|
#### 实现方式
|
||||||
|
|
||||||
用开源的 msm 插件解决 Tomcat 之间的 Session 共享:Memcached_Session_Manager(MSM)
|
用开源的 msm 插件解决 Tomcat 之间的 Session 共享:Memcached_Session_Manager(MSM)
|
||||||
|
|
||||||
## 4. Session 持久化到数据库
|
## 4. Session 持久化到数据库
|
||||||
|
|
||||||
**原理**
|
### 原理
|
||||||
|
|
||||||
拿出一个数据库,专门用来存储 Session 信息。保证 Session 的持久化。
|
拿出一个数据库,专门用来存储 Session 信息。保证 Session 的持久化。
|
||||||
|
|
||||||
**优点**
|
### 优点
|
||||||
|
|
||||||
服务器出现问题,Session 不会丢失
|
服务器出现问题,Session 不会丢失
|
||||||
|
|
||||||
**缺点**
|
### 缺点
|
||||||
|
|
||||||
如果网站的访问量很大,把 Session 存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销维护数据库。
|
如果网站的访问量很大,把 Session 存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销维护数据库。
|
||||||
|
|
||||||
## 5. Terracotta 实现 Session 复制
|
## 5. Terracotta 实现 Session 复制
|
||||||
|
|
||||||
**原理**
|
### 原理
|
||||||
|
|
||||||
Terracotta 的基本原理是对于集群间共享的数据,当在一个节点发生变化的时候,Terracotta 只把变化的部分发送给 Terracotta 服务器,然后由服务器把它转发给真正需要这个数据的节点。它是服务器 Session 复制的优化。
|
Terracotta 的基本原理是对于集群间共享的数据,当在一个节点发生变化的时候,Terracotta 只把变化的部分发送给 Terracotta 服务器,然后由服务器把它转发给真正需要这个数据的节点。它是服务器 Session 复制的优化。
|
||||||
|
|
||||||
<div align="center"> <img src="../pics//b6acae0d-7148-41de-adc3-ff5ff8dca3ae.jpg"/> </div><br>
|
<div align="center"> <img src="../pics//b6acae0d-7148-41de-adc3-ff5ff8dca3ae.jpg"/> </div><br>
|
||||||
|
|
||||||
**优点**
|
### 优点
|
||||||
|
|
||||||
这样对网络的压力就非常小,各个节点也不必浪费 CPU 时间和内存进行大量的序列化操作。把这种集群间数据共享的机制应用在 Session 同步上,既避免了对数据库的依赖,又能达到负载均衡和灾难恢复的效果。
|
这样对网络的压力就非常小,各个节点也不必浪费 CPU 时间和内存进行大量的序列化操作。把这种集群间数据共享的机制应用在 Session 同步上,既避免了对数据库的依赖,又能达到负载均衡和灾难恢复的效果。
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user