auto commit

This commit is contained in:
CyC2018
2018-05-25 15:47:52 +08:00
parent 89f8c5e17a
commit 3cfab5caf2
18 changed files with 394 additions and 341 deletions

View File

@ -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 唯一性
- 使用全局唯一 IDGUID。
- 为每个分片指定一个 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)
- [服务端指南 数据存储篇 | MySQL09 分库与分表带来的分布式困境与应对之策](http://blog.720ui.com/2017/mysql_core_09_multi_db_table2/ "服务端指南 数据存储篇 | MySQL09 分库与分表带来的分布式困境与应对之策")
- [How to create unique row ID in sharded databases?](https://stackoverflow.com/questions/788829/how-to-create-unique-row-id-in-sharded-databases)