什么是CAP理论
CAP理论是分布式领域中非常重要的一个指导理论,C(Consistency)表示强一致性,A(Availability)表示可用性,P(Partition Tolerance)表示分区容错性,CAP理论指出在目前的硬件条件下,一个分布式系统是必须要保证分区容错性的,而在这个前提下,分布式系统要么保证CP,要么保证AP,无法同时保证CAP。
分区容错性表示,一个系统虽然是分布式的,但是对外看上去应该是一个整体,不能由于分布式系统内部的某个结点挂点,或网络出现了故障,而导致系统对外出现异常。所以,对于分布式系统而言是一定要保证分区容错性的。
强一致性表示,一个分布式系统中各个结点之间能及时的同步数据,在数据同步过程中,是不能对外提供服务的,不然就会造成数据不一致,所以强一致性和可用性是不能同时满足的。
什么是BASE理论
由于不能同时满足CAP,所以出现了BASE理论:
- BA:Basically Available,表示基本可用,表示可以允许一定程度的不可用,比如由于系统故障,请求时间变长,或者由于系统故障导致部分非核心功能不可用,都是允许的
- S:Soft state:表示分布式系统可以处于一种中间状态,比如数据正在同步
- E:Eventually consistent,表示最终一致性,不要求分布式系统数据实时达到一致,允许在经过一段时间后再达到一致,在达到一致过程中,系统也是可用的
分布式锁的使用场景是什么?有哪些实现方案?
在单体架构中,多个线程都是属于同一个进程的,所以在线程并发执行时,遇到资源竞争时,可以利用ReentrantLock、synchronized等技术来作为锁,来控制共享资源的使用。
而在分布式架构中,多个线程是可能处于不同进程中的,而这些线程并发执行遇到资源竞争时,利用ReentrantLock、synchronized等技术是没办法来控制多个进程中的线程的,所以需要分布式锁,意思就是,需要一个分布式锁生成器,分布式系统中的应用程序都可以来使用这个生成器所提供的锁,从而达到多个进程中的线程使用同一把锁。
目前主流的分布式锁的实现方案有两种:
- zookeeper:利用的是zookeeper的临时节点、顺序节点、watch机制来实现的,zookeeper分布式锁的特点是高一致性,因为zookeeper保证的是CP,所以由它实现的分布式锁更可靠,不会出现混乱
redis:利用redis的setnx、lua脚本、消费订阅等机制来实现的,redis分布式锁的特点是高可用,因为redis保证的是AP,所以由它实现的分布式锁可能不可靠,不稳定(一旦redis中的数据出现了不一致),可能会出现多个客户端同时加到锁的情况
什么是分布式事务?有哪些实现方案?
在分布式系统中,一次业务处理可能需要多个应用来实现,比如用户发送一次下单请求,就涉及到订单系统创建订单、库存系统减库存,而对于一次下单,订单创建与减库存应该是要同时成功或同时失败的,但在分布式系统中,如果不做处理,就很有可能出现订单创建成功,但是减库存失败,那么解决这类问题,就需要用到分布式事务。常用解决方案有:
本地消息表:创建订单时,将减库存消息加入在本地事务中,一起提交到数据库存入本地消息表,然后调用库存系统,如果调用成功则修改本地消息状态为成功,如果调用库存系统失败,则由后台定时任务从本地消息表中取出未成功的消息,重试调用库存系统
- 消息队列:目前RocketMQ中支持事务消息,它的工作原理是:
- 生产者订单系统先发送一条half消息到Broker,half消息对消费者而言是不可见的
- 再创建订单,根据创建订单成功与否,向Broker发送commit或rollback
- 并且生产者订单系统还可以提供Broker回调接口,当Broker发现一段时间half消息没有收到任何操作命令,则会主动调此接口来查询订单是否创建成功
- 一旦half消息commit了,消费者库存系统就会来消费,如果消费成功,则消息销毁,分布式事务成功结束
- 如果消费失败,则根据重试策略进行重试,最后还失败则进入死信队列,等待进一步处理
- Seata:阿里开源的分布式事务框架,支持AT、TCC等多种模式,底层都是基于两阶段提交理论来实现的
分布式架构下,Session 共享有什么方案
1、采用无状态服务,抛弃session
2、存入cookie(有安全风险)
3、服务器之间进行 Session 同步,这样可以保证每个服务器上都有全部的 Session 信息,不过当服务器数量比较多的时候,同步是会有延迟甚至同步失败;
4、 IP 绑定策略
使用 Nginx (或其他复杂均衡软硬件)中的 IP 绑定策略,同一个 IP 只能在指定的同一个机器访问,但是这样做失去了负载均衡的意义,当挂掉一台服务器的时候,会影响一批用户的使用,风险很大;
5、使用 Redis 存储
把 Session 放到 Redis 中存储,虽然架构上变得复杂,并且需要多访问一次 Redis ,但是这种方案带来的好处也是很大的:
- 实现了 Session 共享;
- 可以水平扩展(增加 Redis 服务器);
- 服务器重启 Session 不丢失(不过也要注意 Session 在 Redis 中的刷新/失效机制);
- 不仅可以跨服务器 Session 共享,甚至可以跨平台(例如网页端和 APP 端)。