分布式幂等性如何设计?
根据业务场景建立唯一索引、或者建立组合索引,这样防止产生脏数据
token机制:通过redis来实现防重复提交
悲观锁
乐观锁
分布式锁
简单描述一下HTTP请求的过程
DNS解析
HTTP请求,当输入一个请求时,会进行TCP3次握手
客户端向服务端发送请求命令(Post、Get)
客户端发送请求头信息
服务端向客户端发送数据
服务端关闭TCP连接
客户端渲染
说说你对分布式事务的了解
ACID:
A:原子性
C:一致性
I:隔离性
D:持久性
ACP:
A:一致性:同一时刻不同节点是否保持一致
C:可用性:在某一节点出现问题时,是否还可以对外提供服务
P:分区容错性:A和C必须保证一个
BASE理论:是对CAP理论的一个权衡结果,我们复发做到强一致性,但是每个应用可以根据自身的特点,采用适当的方式来达到最终一致性。
分布式事务解决方案
两阶段提交(2PC)
三阶段提交(3PC)
补偿事务(TCC)
本地消息队列
最终一致性
负载均衡有哪些算法
随机
轮询
加权轮询
最少连接
源地址hash
常见的限流算法
计数器
使用计数器在周期内累加访问次数,当达到设定的限流值,触发限流策略,下一个周期开始时从新开始计数。(在单机或者分布式情况下,可以采用redis的incr原子自增操作来实现)。零界点问题。
滑动窗口
将时间分成很多个小周期,分别记录每个小周期内访问次数,并且根据时间滑动删除过期的小周期。
漏桶算法
访问请求到来时,直接放入漏桶,如当前容量已达到上限,则直接进行丢弃。
令牌桶算法
是以固定的算法(r=时间周期/限流值)的速度向令牌桶中加入令牌,直到令牌桶满,请求到达时向令牌桶获取令牌,获取成功则继续执行,获取失败则触发限流策略。
数据库如何处理海量数据
对数据库进行:分库分表、主从架构、读写分离。
如何提高系统的并发能力?
使用分布式服务器
部署多台服务器,做负载均衡
数据库分库分表、读写分离
引入业务需要的中间件
关于分布式事务
参考资料
https://blog.51cto.com/u_15499328/5159840?b=totalstatistic
2PC 二阶段提交
二阶段提交是一种强一致设计,2PC引入一个协调者来管理各个参与者的提交和回滚,二阶段分别是指准备和提交两个阶段。
它是同步阻塞的,而且同步阻塞长时间会导致资源锁的问题,总体而言效率低,并且存在单点故障,在极端条件下存在数据不一致问题。
2PC适应于数据库层面分布式事务应用场景。
3PC 三阶段提交
参与者也引入超时机制,并且新增了一个阶段使得参与者利用这一阶段统一各自的状态
3PC:准备阶段、预提交阶段、提交阶段。多引入一个阶段也会多一些交互,因此 性能会差一些。引入参与者超时机制。
2PC、3PC都是数据库层面的。
TCC(Try - Confirm - Cancel)
2PC 和 3PC 都是数据库层面的、而TCC是业务层面的分布式事务。
Try:预留、资源的预留和锁定
Confirm:确认操作,真正的执行
Cancel:撤销操作,把预留阶段的操作取消掉
其实思想上和2PC都差不多,都是先试探性执行,如果都可以那就真正执行,如果不行就回滚。
TCC对业务侵入较大,与业务紧耦合,需根据特定的业务场景来设计,
撤销和确认操作可能需要重试,要保证接口的幂等性。
TCC需要自定义,可实现跨数据库、跨不同业务系统来实现事务。
本地消息表
利用各个系统的本地事务来实现分布式事务。
有一张存放本地消息表,一般都放在数据库中,然后在执行业务的时候,将业务的执行和消息放入消息表放在同一个事务中,这样就能保证消息放入本地表中业务肯定是执行成功的。
如果调用失败,会有 定时任务定时读取本地消息表,实现最终一致性。
消息事务
RocketMQ 支持消息事务
第一步通过发送半消息,这个消息对于消费者来说不可见,然后发送成功后再执行本地事务。
再根据本地事务向broker发送Commit还是RollBack命令
并且RocketMq会提供反查事务状态接口,
RocketMq也是通过最终一致性来实现的。
最大努力通知
最大努力通知其实表示就是柔性事务的思想:我已经尽最大努力想达成事务的最终一致性。适用于对时间不敏感的业务,如短信通知等。
秒杀系统如何设计
秒杀服务子系统
就算秒杀系统挂了,不影响其他服务,【服务降价】
页面静态化
活动页面是流量第一入口,活动页面大都是固定的:商品名称、描述、图片等。为了减少不必要的服务端请求,页面会做静态化处理,用户常规浏览SKU的时候不会请求服务端。
静态化CND,内容分发网络。
前端处理
前端加一个定时器:比如5s之内只能发送一次服务端请求,然后秒杀按钮置灰。等限制时间过了又可以继续点击。
数据库读多写少
大部分查询走 Redis
缓存问题 Redis集群
通常情况下,我们需要在Redis中存商品信息,里面包含:商品编码、商品名称、商品属性、商品库存等信息。
优先查询缓存中数据是否存在,不存在再查询数据库。【缓存预热】
不存在的商品直接缓存为空,下次来查询直接用,缓存穿透问题。
数据库库存扣减问题
可以通过乐观锁解决
Redis lua 脚本扣减库存
先判断商品是否存在、如果不存在则直接返回
获取sku库存信息
如果库存大于0,则进行库存扣减
如果库存等于0,则直接返回表示库存不足
mq异步处理
消息丢失问题:本地记录消息表,本地记录成功再发送mq队列,有失败的消息通过job机制
延迟消息队列:订单超时取消。
限流
基于Nginx限流、基于Redis限流
基于用户限流、基于IP限流。
加验证码限流:三方验证码-滑块验证码。
基于业务限流:会员体系,限制条件。