1.什么是分布式系统?用过那些分布式系统?
一个业务分拆多个子业务,部署在不同的服务器上。
dubbo、spring cloud
2.分布式锁
1.基于数据库实现分布式锁
2.基于缓存redis实现分布式锁 (设置超时时间)
3.基于Zookeeper实现分布式锁(临时节点)
3.分布式缓存
redis、Memcached
redis和Memcached区别
1 、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2 、Redis支持数据的备份,即master-slave模式的数据备份。
3 、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
4 、redis是单线程,memcached是多线程
4.分布式redis缓存击穿
1、使用互斥锁排队:根据key获取value值为空时,锁上,从数据库中load数据后再释放锁。
若其它线程获取锁失败,则等待一段时间后重试。
2、接口限流与熔断、降级:重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,
当接口中的某些服务不可用时候,进行熔断,失败快速返回机制(Hystrix:服务熔断,服务降级)
3、布隆过滤器:bloomfilter就类似于一个hash set,用于快速判某个元素是否存在于集合中,
其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。
5.分布式缓存雪崩
缓存在同一时间内大量键过期(失效),接着来的一大波请求瞬间都落在了数据库中导致连接异常。
解决方案:
方案1、也是像解决缓存穿透一样加锁排队,实现同上;
方案2、建立备份缓存,缓存A和缓存B,A设置超时时间,B不设值超时时间,先从A读缓存,A没有读B,
并且更新A缓存和B缓存;
方案3、设置缓存超时时间的时候加上一个随机的时间长度,比如这个缓存key的超时时间是固定的5分钟
加上随机的2分钟,酱紫可从一定程度上避免雪崩问题;
6.分布式框架(dubbo、springcloud)
eureka:服务发现注册
ribbon:负载均衡
feign:远程调用
hystrix:熔断
zuul:过滤路由
dubbo架构:
服务容器负责启动,加载,运行服务提供者。
服务提供者(生产者)在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,(异步通知)定时每分钟发送一次统计数据到监控中心
7.分布式会话共享(session),分布式Session一致性?(单点登录问题)
session同步法:
1.session复制(同步):多个web-server之间相互同步session,这样每个web-server之间都包含全部
的session
2.客户端存储法:服务端存储所有用户的session,内存占用较大,可以将session存储到浏览器cookie中,
每个端只要存储一个用户的数据了
3.后端统一存储:将session存储在web-server后端的存储层,数据库或者缓存 (最佳方法)
8.CAP原则(zookeeper、eureka)
C:一致性
A:可用性
P:分区容错性
CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、
Partition tolerance(分区容错性),三者不可得兼,是NOSQL数据库的基石。
只能:
CP:放弃可用性,追求一致性和分区容错性 (zookeeper)
AP:放弃一致性,追求放弃容错性和可用性(eureka)
9.BASE 原则
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)
三个短语的缩写,是对 CAP 中 AP 的一个扩展。
基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是 CAP 中的不一致。
最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。
10.分布式事务
两阶段提交方案/XA方案
所谓的 XA 方案,即:两阶段提交,有一个事务管理器的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。
这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发的场景。如果要玩儿,那么基于 Spring + JTA 就可以搞定,自己随便搜个 demo 看看就知道了。
这个方案,我们很少用,一般来说某个系统内部如果出现跨多个库的这么一个操作,是不合规的。我可以给大家介绍一下, 现在微服务,一个大的系统分成几十个甚至几百个服务。一般来说,我们的规定和规范,是要求每个服务只能操作自己对应的一个数据库。
如果你要操作别的服务对应的库,不允许直连别的服务的库,违反微服务架构的规范,你随便交叉胡乱访问,几百个服务的话,全体乱套,这样的一套服务是没法管理的,没法治理的,可能会出现数据被别人改错,自己的库被别人写挂等情况。
如果你要操作别人的服务的库,你必须是通过调用别的服务的接口来实现,绝对不允许交叉访问别人的数据库。
TCC 方案
TCC 的全称是:Try、Confirm、Cancel。
Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留。
Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。
Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
这种方案说实话几乎很少人使用,我们用的也比较少,但是也有使用的场景。因为这个事务回滚实际上是严重依赖于你自己写代码来回滚和补偿了,会造成补偿代码巨大,非常之恶心。
比如说我们,一般来说跟钱相关的,跟钱打交道的,支付、交易相关的场景,我们会用 TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题。
而且最好是你的各个业务执行的时间都比较短。
但是说实话,一般尽量别这么搞,自己手写回滚逻辑,或者是补偿逻辑,实在太恶心了,那个业务代码是很难维护的。
可靠消息最终一致性方案
直接基于 MQ 来实现事务。比如阿里的 RocketMQ 就支持消息事务。
大概的意思就是:
A 系统先发送一个 prepared 消息到 mq,如果这个 prepared 消息发送失败那么就直接取消操作别执行了;
如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉 mq 发送确认消息,如果失败就告诉 mq 回滚消息;
如果发送了确认消息,那么此时 B 系统会接收到确认消息,然后执行本地的事务;
mq 会自动定时轮询所有 prepared 消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。
这个方案里,要是系统 B 的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。。
11.反向代理和负载均衡有何区别?
服务器负载均衡:在多个提供相同服务的服务器的情况下,负载均衡设备存在虚拟服务IP地址。当大量客户端从外部访问虚拟服务IP地址时,负载均衡设备将这些报文请求根据负载均衡算法,将流量均衡的分配给后台服务器以平衡各个服务器的负载压力,避免在还有服务器压力较小情况下其他服务达到性能临界点出现运行缓慢甚至宕机情况,从而提高服务效率和质量。因此对客户端而言,RS(real server 实际服务器)的IP地址即是负载均衡设备VIP(虚拟服务地址IP)地址,真正的RS服务器IP地址对于客户端是不可见的。
反向代理:普通的代理设备是内网用户通过代理设备出外网进行访问,而工作在这种模式下的负载均衡设备,则是外网用户通过代理设备访问内网,因此称之为反向代理。
12.注册中心挂了可以继续通信吗?
可以,因为刚开始初始化的时候,消费者会将提供者的地址等信息拉取到本地缓存,所以注册中心挂了可以继续通信。
13.dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
通信协议:
1.dubbo 协议(默认):默认就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
2.rmi 协议:走 Java 二进制序列化
3.hessian 协议:走 hessian 序列化协议
4.http 协议:走 json 序列化。
5.webservice:走 SOAP 文本序列化
序列化协议:支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。
Hessian 的数据结构:8种
PB:Protocol Buffer,第一,它使用 proto 编译器,自动进行序列化和反序列化,速度非常快,应该比 XML 和 JSON 快上了 20~100 倍;第二,它的数据压缩效果好,就是说它序列化后的数据量体积小。因为体积小,传输起来带宽和速度上会有优化。
14.dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?
负载均衡策略:
1.随机调用实现负载均衡,可以对 provider 不同实例设置不同的权重
2.均匀地将流量打到各个机器上去
集群容错策略:
1.失败自动切换,自动重试其他机器,默认就是这个,常见于读操作
2.一次调用失败就立即失败,常见于非幂等性的写操作,比如新增一条记录
3.出现异常时忽略掉,常用于不重要的接口调用,比如记录日志。
4.失败了后台自动记录请求,然后定时重发,比较适合于写消息队列这种。
dubbo动态代理策略:
默认使用 javassist 动态字节码生成,创建代理类。但是可以通过 spi 扩展机制配置自己的动态代理策略。
spi,简单来说,就是 service provider interface,说白了是什么意思呢,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要 spi 了,需要根据指定的配置或者是默认的配置,去找到对应的实现类加载进来,然后用这个实现类的实例对象。