1.design_purpose
什么是分布式系统?
一个分布式系统, 从物理上说是 用户 -network- 多台服务器主机 形成的一个特殊的系统
如果对这个模型进行抽象, 其实就是 单个terminal 和 多个 process 之间的通信,
其中, 这些 process 空间上分离, 通过网络进行通信, 不应该存在明显延迟, 并且命运不同(一台主机挂了不应该影响其他主机)
从上面的抽象系统目标, 我们还可以更加抽象出分布式系统的设计目标:
- High availability: 整体的分布式系统应当永远可用
- Low latency: 用户请求的响应时间应当足够低
- Scalability: 系统支持同时服务多个用户
…
银行后端为例
分布式系统设计的困难可以分为以下几个难点:
- concurrency: 多个 process 之间的并发控制, 但是之间的网络不可靠,
主机状态不可靠 - inconsistency: 数据交换一定会存在可见延迟
- ambiguity: 一个存款请求需要等待下游主机反馈
ACK, 但是如果没有收到, 如何判断是哪一步出了问题? 存款是否成功?
channel 管道实现的同步
rendezvous 汇合同步
管道天生就具有其堵塞的属性, 也就是说, 管道的设置会要求管道双方在管道传输处建立一个握手, 只有完成了握手 (双方同时到达) 才能继续执行
在 for-select 语法中, 往往会用三种方式来使用管道
1 | // 1. 读取: 看到 =<- 这样的写法就说明这里是一个读取操作, 也就是等待另一端有数据发送过来 |
for-select 中央引擎
对于一个类封装的时候, 如果这个类要支持并发且有同步操作, 往往会在一个中央函数中
(很有可能在初始化函数中直接开一个 goroutine 来运行) 加入这个 for-select
引擎来支持并发, 这有以下几个好处:
- 单一线程同时监听多个 channel, 比如设计了一个 manager 其手下有多个
worker, 那么这个 manager 可以 select 多个 worker.ch 来判断工人是否完成了任务, 或者查看是否有下游的 worker 在等待任务的分发 - 支持随时收到 term 信号来实现程序的优雅退出
- confinement: 由于单一 goroutine 线程能通过这个
for-select
引擎同时监管多个 channel 的资源, 所以这里实际上已经要求将所有的资源集中化管理, 也就是这里强制这个 select 所在的环境函数对这些资源具有所有权, 而为了减少对应 chan 的随便乱传 (串子司马) 程序设计的时候更倾向于直接将对应 channel 写成当前类的资源
不过注意这里的 term 终止 channel 一般是每个对应有 for-select
的类都会具有的一个自身 channel
分布式语言的 代码约束 (Confinement)
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
