auto commit
This commit is contained in:
@ -11,14 +11,6 @@
|
||||
* [使用场景](#使用场景)
|
||||
* [实现方式](#实现方式)
|
||||
* [五、分布式 Session](#五分布式-session)
|
||||
* [1. Sticky Sessions](#1-sticky-sessions)
|
||||
* [2. Session Replication](#2-session-replication)
|
||||
* [3. Persistent DataStore](#3-persistent-datastore)
|
||||
* [4. In-Memory DataStore](#4-in-memory-datastore)
|
||||
* [六、分库与分表带来的分布式困境与应对之策](#六分库与分表带来的分布式困境与应对之策)
|
||||
* [事务问题](#事务问题)
|
||||
* [查询问题](#查询问题)
|
||||
* [ID 唯一性](#id-唯一性)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
@ -59,24 +51,24 @@
|
||||
|
||||
#### 2.1 消息处理模型
|
||||
|
||||
(一)消息队列
|
||||
**(一)消息队列**
|
||||
|
||||
<div align="center"> <img src="../pics//96b63e13-e2d8-4ddb-9aa1-a38959ca96e5.jpg" width="700"/> </div><br>
|
||||
|
||||
(二)发布/订阅
|
||||
**(二)发布/订阅**
|
||||
|
||||
<div align="center"> <img src="../pics//654acfed-a6a5-4fc7-8f40-3fdcae57bae8.jpg" width="700"/> </div><br>
|
||||
|
||||
|
||||
#### 2.2 消息的可靠性
|
||||
|
||||
(一)发送端的可靠性
|
||||
**(一)发送端的可靠性**
|
||||
|
||||
发送端完成操作后一定能将消息成功发送到消息系统。
|
||||
|
||||
实现方法:在本地数据库建一张消息表,将消息数据与业务数据保存在同一数据库实例里,这样就可以利用本地数据库的事务机制。事务提交成功后,将消息表中的消息转移到消息中间件,若转移消息成功则删除消息表中的数据,否则继续重传。
|
||||
|
||||
(二)接收端的可靠性
|
||||
**(二)接收端的可靠性**
|
||||
|
||||
接收端能够从消息中间件成功消费一次消息。
|
||||
|
||||
@ -115,9 +107,9 @@
|
||||
|
||||
<div align="center"> <img src="../pics//1f4a7f10-52b2-4bd7-a67d-a9581d66dc62.jpg"/> </div><br>
|
||||
|
||||
### 4. 加权最小连接(Weighted Least Connection)
|
||||
### 4. 加权最少连接(Weighted Least Connection)
|
||||
|
||||
在最小连接的基础上,根据服务器的性能为每台服务器分配权重,再根据权重计算出每台服务器能处理的连接数。
|
||||
在最少连接的基础上,根据服务器的性能为每台服务器分配权重,再根据权重计算出每台服务器能处理的连接数。
|
||||
|
||||
<div align="center"> <img src="../pics//44edefb7-4b58-4519-b8ee-4aca01697b78.jpg"/> </div><br>
|
||||
|
||||
@ -200,9 +192,9 @@ Java 提供了两种内置的锁的实现,一种是由 JVM 实现的 synchroni
|
||||
|
||||
这种方式存在以下几个问题:
|
||||
|
||||
1. 锁没有失效时间,解锁失败会导致死锁,其他线程无法再获得锁。
|
||||
2. 只能是非阻塞锁,插入失败直接就报错了,无法重试。
|
||||
3. 不可重入,同一线程在没有释放锁之前无法再获得锁。
|
||||
- 锁没有失效时间,解锁失败会导致死锁,其他线程无法再获得锁。
|
||||
- 只能是非阻塞锁,插入失败直接就报错了,无法重试。
|
||||
- 不可重入,同一线程在没有释放锁之前无法再获得锁。
|
||||
|
||||
**(二)采用乐观锁增加版本号**
|
||||
|
||||
@ -218,11 +210,11 @@ EXPIRE 可以为一个键值对设置一个过期时间,从而避免了死锁
|
||||
|
||||
**(二)RedLock 算法**
|
||||
|
||||
RedLock 算法使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时还可用。
|
||||
RedLock 算法使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时仍然可用。
|
||||
|
||||
1. 尝试从 N 个相互独立 Redis 实例获取锁,如果一个实例不可用,应该尽快尝试下一个。
|
||||
2. 计算获取锁消耗的时间,只有当这个时间小于锁的过期时间,并且从大多数(N/2+1)实例上获取了锁,那么就认为锁获取成功了。
|
||||
3. 如果锁获取失败,会到每个实例上释放锁。
|
||||
- 尝试从 N 个相互独立 Redis 实例获取锁,如果一个实例不可用,应该尽快尝试下一个。
|
||||
- 计算获取锁消耗的时间,只有当这个时间小于锁的过期时间,并且从大多数(N/2+1)实例上获取了锁,那么就认为锁获取成功了。
|
||||
- 如果锁获取失败,会到每个实例上释放锁。
|
||||
|
||||
### 3. Zookeeper 分布式锁
|
||||
|
||||
@ -246,10 +238,10 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
|
||||
**(四)分布式锁实现**
|
||||
|
||||
1. 创建一个锁目录 /lock。
|
||||
1. 在 /lock 下创建临时的且有序的子节点,第一个客户端对应的子节点为 /lock/lock-0000000000,第二个为 /lock/lock-0000000001,以此类推。
|
||||
2. 客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听自己的前一个子节点,获得子节点的变更通知后重复此步骤直至获得锁;
|
||||
3. 执行业务代码,完成后,删除对应的子节点。
|
||||
- 创建一个锁目录 /lock;
|
||||
- 在 /lock 下创建临时的且有序的子节点,第一个客户端对应的子节点为 /lock/lock-0000000000,第二个为 /lock/lock-0000000001,以此类推;
|
||||
- 客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听自己的前一个子节点,获得子节点的变更通知后重复此步骤直至获得锁;
|
||||
- 执行业务代码,完成后,删除对应的子节点。
|
||||
|
||||
**(五)会话超时**
|
||||
|
||||
@ -257,7 +249,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
|
||||
**(六)羊群效应**
|
||||
|
||||
在步骤二,一个节点未获得锁,需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。
|
||||
一个节点未获得锁,需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。
|
||||
|
||||
# 五、分布式 Session
|
||||
|
||||
@ -265,7 +257,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
|
||||
<div align="center"> <img src="../pics//cookiedata.png"/> </div><br>
|
||||
|
||||
## 1. Sticky Sessions
|
||||
### 1. Sticky Sessions
|
||||
|
||||
需要配置负载均衡器,使得一个用户的所有请求都路由到一个服务器节点上,这样就可以把用户的 Session 存放在该服务器节点中。
|
||||
|
||||
@ -273,7 +265,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
|
||||
<div align="center"> <img src="../pics//MultiNode-StickySessions.jpg"/> </div><br>
|
||||
|
||||
## 2. Session Replication
|
||||
### 2. Session Replication
|
||||
|
||||
在服务器节点之间进行 Session 同步操作,这样的话用户可以访问任何一个服务器节点。
|
||||
|
||||
@ -281,7 +273,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
|
||||
<div align="center"> <img src="../pics//MultiNode-SessionReplication.jpg"/> </div><br>
|
||||
|
||||
## 3. Persistent DataStore
|
||||
### 3. Persistent DataStore
|
||||
|
||||
将 Session 信息持久化到一个数据库中。
|
||||
|
||||
@ -289,28 +281,10 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
|
||||
<div align="center"> <img src="../pics//MultiNode-SpringSession.jpg"/> </div><br>
|
||||
|
||||
## 4. In-Memory DataStore
|
||||
### 4. In-Memory DataStore
|
||||
|
||||
可以使用 Redis 和 Memcached 这种内存型数据库对 Session 进行存储,可以大大提高 Session 的读写效率。内存型数据库同样可以持久化数据到磁盘中来保证数据的安全性。
|
||||
|
||||
# 六、分库与分表带来的分布式困境与应对之策
|
||||
|
||||
<div align="center"> <img src="../pics//f3d3e072-e947-43e9-b999-22385fd569a0.jpg"/> </div><br>
|
||||
|
||||
## 事务问题
|
||||
|
||||
使用分布式事务。
|
||||
|
||||
## 查询问题
|
||||
|
||||
使用汇总表。
|
||||
|
||||
## ID 唯一性
|
||||
|
||||
- 使用全局唯一 ID:GUID。
|
||||
- 为每个分片指定一个 ID 范围。
|
||||
- 分布式 ID 生成器 (如 Twitter 的 [Snowflake](https://twitter.github.io/twitter-server/) 算法)。
|
||||
|
||||
# 参考资料
|
||||
|
||||
- [Comparing Load Balancing Algorithms](http://www.jscape.com/blog/load-balancing-algorithms)
|
||||
@ -324,6 +298,3 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示
|
||||
- [分布式系统的事务处理](https://coolshell.cn/articles/10910.html)
|
||||
- [关于分布式事务](http://blog.csdn.net/suifeng3051/article/details/52691210)
|
||||
- [基于 Zookeeper 的分布式锁](http://www.dengshenyu.com/java/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/10/23/zookeeper-distributed-lock.html)
|
||||
- [How Sharding Works](https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6)
|
||||
- [服务端指南 数据存储篇 | MySQL(09) 分库与分表带来的分布式困境与应对之策](http://blog.720ui.com/2017/mysql_core_09_multi_db_table2/ "服务端指南 数据存储篇 | MySQL(09) 分库与分表带来的分布式困境与应对之策")
|
||||
- [How to create unique row ID in sharded databases?](https://stackoverflow.com/questions/788829/how-to-create-unique-row-id-in-sharded-databases)
|
||||
|
Reference in New Issue
Block a user