分布式缓存?分布式锁?分布式消息队列?

1.分布式?

集中式系统:所有的功能,所有的服务都在同一个机器上。

对用户来说是单机,但是实际上,两个进程运行在两个机器上,共同协作完成同一个服务或者功能。如果这两个进程完全相同,那么可以叫做集群。

2.分布式系统特性?

“A distributed system is a collection of independent computers that appears to its users as a single coherent system”

分布式系统是独立计算机的集合,在其用户看来是一个单一的连贯系统”。

分布式系统的每一个节点高度自治。

分布式系统对用户来说是透明的。

分布式系统下,当任务量增加的时候,增加服务器的数量,任务减少的时候,减少服务的数量。(动态伸缩)

So,总结一下就是内聚性透明性可扩展可用性可靠性高性能一致性

3.分布式系统常见问题

3.1 分布式系统中-网络不是可靠的

分布式系统的三态!!!

成功/失败/超时。在单个机器上调用一个函数,只有两种状态:成功,失败。但是 A 节点 对 B 节点发起 RPC 调用,B 节点在返回消息给 A 节点的时候,可能超时。

消息丢失:

消息丢失是最常见的网络异常。对于常见的 IP 网络,网络层不保证数据报文的可靠传递,在发生网络拥塞、路由变动、设备异常等情况时,可能出现发送数据丢失的问题。

网络分区:

网络分区可以理解为原来的分布式系统因网络分区而形成了两个系统。

消息乱序:

消息乱序是指节点发送的网络消息有一定的概率不是按照发送时的顺序依次到达目的节点。

数据错误:

网络上传输的数据有可能发生比特错误,从而造成数据错误。通常使用一定的校验码机制可以较为简单的检查出网络数据的错误,从而主动丢弃错误的数据。

3.2 分布式系统中-节点可能故障

不确定计算机什么时候宕机、断电,不确定磁盘什么时候损坏,不确定每次网络通信要延迟多久,也不确定通信对端是否处理了发送的消息。而分布式系统的规模又放大了这种不确定性。

3.3 CAP 理论

多写几遍我总能记住…..

P(PartitionTolerance):分布式系统中,节点间通过网络进行通信,然而可能因为一些故障,导致有些节点之间不连通,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中,从而形成了分区。

解决网络分区的办法就是:数据复制到多个节点。数据的副本越多,数据的分区容忍性越好。

A(Availability):用户的每个请求都能接受到一个响应。 C(Consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据.

CAP 典型的:鱼和熊掌不可兼得

4.分布式中间件——缓存

用来干什么?答:缓存基于内存。DB 基于磁盘。

分布式缓存的主要应用场景有:

页面缓存:

页面缓存存 HTML

应用对象缓存:

作为 ORM 框架的二级缓存对外提供服务。

状态缓存:

缓存 Session 会话状态以及横向扩展时的状态数据。

并行处理:

涉及大量中间计算结果需要共享

事件处理:

针对事件流的连续查询进行处理

5.分布式中间件——锁

单个进程有编程语言层面支持的锁。但是对于多进程,多线程,分布在不同的节点的情况就需要分布式锁。

5.1 原子性/可见性/有序性 问题

原子性:操作不可以中断。

可见性:一个线程对共享变量的修改立即被其他进程要看到。(不能两个进程同时对一个变量的一种状态进行修改)

有序性:

// 进程1
var str="Hello"
// 进程2
str.ToUpper()

进程 1 先执行,进程 2 再执行,可以正常执行。但是进程 2 先执行,进程 1 次执行。那么就会报空指针异常。

5.2 锁机制

用来干什么? 答:在高并发场景下,为了保证共享资源在统一时刻被同一个进程执行,对共享资源加锁。

synchronized 及 Lock 的实现原理 synchronized 本质上是通过锁来实现的。对于同一个代码块,为了实现多个线程在一个时刻只能有一个线程执行,需要在某个地方做个标记,每个线程都必须能看到它。当标记不存在时,某个线程可以设置该标记,其余后续线程发现已经有标记了,则等待拥有标记的线程结束同步代码块取消标记后,再去尝试设置标记。这个标记可以理解为锁。

不同地方实现锁的方式也不一样,只要能满足所有线程都能看得到标记即可。如 Java 中 synchronize 是在对象头设置标记;Lock 接口的实现类的基本思想是,用一个 volitile 修饰的 int 型变量,保证每个线程都能拥有对该 int 的可见性和原子修改。

5.3 分布式场景

不管是 java 还是 golang ,锁机制有效的前提是:同一个进程。但是对于分布式,是跨进程。那么需要一个第三方系统,常见的分布式锁有三个:数据库,缓存,分布式协调系统。

6. 分布式中间件-消息队列

用来干什么?答:应用耦合,削峰,异步

6.1 典型应用场景-异步

一个实际的场景:用户注册,发送注册邮件和短信

串行处理:写入用户信息到数据库——发送注册邮件——发送注册短信

并行处理:

写入用户信息到数据库——发送注册邮件(发送注册短信)

用户一旦按下注册信息的提交按钮,那么就知道了邮箱,手机号,以及写入到数据库的信息,那么这三个动作可以同时进行。

异步处理:

写入用户信息到数据库——把要求发送注册邮件的信息和(要求发送注册短信的信息)写入到消息队列——消息队列被相应的服务消费消息。

6.2 典型应用场景-解耦

一个实际的场景:订单系统和库存系统。当用户下单后,订单系统会调用库存系统将库存减 1.

解耦处理:用户下单后,订单系统完成持久化处理,把(要求库存系统处理)的消息写入消息队列,这个时候返回用户下单成功,消息的发送者发送完

6.3 典型应用场景-削峰

一个实际的场景:双 11,当外部的的请求暴增,这个时候如果引入消息队列,用户的秒杀请求被写入消息队列,并且当请求数量超过消息队列的最大长度,那么超过的请求将会被抛弃,跳转到失败页面。而且秒杀业务是根据消息队列中的请求信息根据数据的实际 select 、insert、update 能力处理注册,预约申请。

6.4 典型应用场景-消息通讯

微信群聊是如何实现的? 答:A 通过客户端发送消息到群,服务把消息写入消息队列;消息队列负责消息的接收,存储和转发,B 通过客户端查看群消息,订阅并消费消息队列中间的信息。

总结

从 CAP 理论切入,学习了三大分布式中间件:分布式缓存、分布式锁以及分布式消息队列。

Tags: 分布式
Share: X (Twitter) Facebook LinkedIn