一、需求和解决方案(以商城项目为例)
没有最优方案,只有最适合方案。业务量和业务需求不同,需要的方案也会不同。某个方案在某种业务背景下合适,放到另外一个业务需求下可能并不合适。
(一)减库存和支付订单的顺序问题
1.先扣减库存再支付
如果有人恶意刷单不支付订单会影响商品正常售卖。这种情况针对客户端可以限制每个IP每天的下单数量;针对服务器端当用户下订单并扣减库存后立马锁定库存,半个小时如果用户没有支付订单或者订单支付失败则自动释放库存给其他用户购买。
2.先支付再扣减库存
如果用户已经支付,后面库存不够给用户发货了就需要给用户退款,这会给用户造成很不好的体验。针对这种情况可以借助消息中间件来实现支付和扣减库存的解耦,当用户支付成功后发送支付成功的消息到MQ,当订单服务监听消息队列中支付成功的消息后扣减库存。
二、亮点/难点
(一)遇到的问题,分析方法,解决方案、上线情况
star(situation、task、action、result),遇到什么问题?在完成什么任务时遇到这个问题的?遇到问题后的行动是什么?执行行动后上线后的结果是什么?
(二)案例一:缓存
在开发完XXX服务进行压测时发现,当QPS达到5000时整个服务的响应时间在3s左右,这个响应时间对用户来说是不能接受的,因此尝试通过加Redis缓存来提高系统响应时间,在把数据加入缓存时对数据进行了分析,只把请求频率比较高的数据加入缓存以保证缓存的高速响应。上线之后发现整个系统的响应时间由原来的3s左右变成了50ms左右,数据响应时间整整提高5倍左右。
(三)案例二:Hystrix隔离策略
在使用SpringCloud Alibaba体系下的Feign组件进行RPC远程服务调用时,Hystrix熔断组件的隔离级别应该设置成SEMAPHORE而不是THREAD,前者是信号量隔离模式后者是线程池隔离模式(Hystrix组件默认的隔离模式),在线程池隔离模式下当前服务是拿不到远程服务的实例的因此无法完成远程服务中方法的调用,因为THREAD里面是通过ThreadLocal实现的,而ThreadLocal是线程私有的,所以在当前服务的主线程中拿不到子线程中的远程服务的实例。而SEMAPHORE是线程共享的设计思想,因此主线程可以拿到子线程中远程服务的实例并完成远程服务中目标方法的调用。
三、分布式锁
分布式锁的实现有四种方式:Mysql、etcd、Redis、Zookeeper,最后两种方式使用较多。
(一)Redis实现分布式锁(高性能)
如果要实现高性能的分布式锁就选择通过Redis来实现,其缺陷是如果只是在单个机器上实现分布式锁,这台机器宕机那么其中的锁业务就会瘫痪。因此,一般情况下是本着“一主二从三哨兵”的原则在多态机器上实现分布式锁,但是在多台机器上实现分布式锁会存在数据一致性问题,就是用户1在主节点上已经加锁成功,其锁资源还没有及时同步到从节点就挂了,那么用户2又可以从从节点获取到锁资源,其实用户1此时已经持有了Redis的锁资源还未释放,这个时候用户2再获取到锁资源是不合理的,这就是Redis实现分布式锁虽然高性能但存在的问题。
(二)Zookeeper实现分布式锁(高一致性)
相比Redis来说,Zookeeper通过多个节点实现分布式锁就不存在数据一致性问题,因为它里面存在投票原则、超过半数以上的节点写锁成功才算获得锁资源。
四、分布式事务
分三阶段提交和两阶段提交,其区别是前者多了一个确认阶段。真正使用时很少项目实现三阶段提交,因为没必要。Seata是比较常见的分布式事务解决方案。
五、分布式ID
分布式ID应该具备的特性:全局唯一、高性能、高可用、好接入。分布式ID不应该自增(顺序性),否则保证不了安全性,因此需要做到不可预测性,避免被恶意爬到。
(一)实现方案
uuid、数据库自增(假如有两张表,分库分表时需注意别重复了。可以把步长设置成2,一张表id为1/3/5…,另一张表2/4/6/8…)、数据库号段、雪花算法。
(二)分布式系统风险及解决方案
1.引入第三方会存在一定风险,可以通过集群来保证高可用
2.数据不一致:通过补偿方式解决
3.服务整体性能会降低。因为一个服务可能扛不住高并发
六、前端优化
(一)目的:减少后端处理压力
(二)原则:4要1不要
1.数据要尽量少(压缩)
2.请求数要尽量少(合并,??css,a.css,b.css)
3.路径要尽量短
4.依赖尽量少(服务依赖其他服务越少越好)
5.不要单点(出于高可用考虑,单个服务宕机前端请求无法处理)
七、客户端和服务端之间的优化
(一)cache-control
用来控制缓存存在于客户端还是存在于各级代理以及交换机在页面上的缓存,也就是可以控制请求从前端发送到后端服务器的过程中哪些环节对请求做了缓存,它是通过请求来控制的。
(二)dns
主要用dns做负载均衡,除此之外还可以用于做域名解析。在从一个页面跳转到另外一个页面的场景中,访问当前页面时就开始做下一个页面访问时的域名解析以加快访问速度。
(三)cdn
将数据缓存在多个节点中,用户从最近的节点访问数据以加快访问速度。
八、服务端优化
(一)并发,集群
能并发则并发。
1.无状态节点集群
不记录登录状态。好处在于可以无限横向扩展集群。
2.单一服务节点集群
一种负载均衡的策略。比如10个用户编号分别为1/2/3…10,单数请求进入A服务器,双数编号请求进入B服务器,通过这种方式将请求和服务器对应固定起来。
3.共享信息集群
这是最常用的一种集群方式。比如多个服务共用同一个数据库,这个时候数据库将会成为瓶颈,可以通过读写分离、分库分表的方式解决。
4.信息一致集群
一个服务和一个数据库组件一个单元,多个单元中的数据库之间进行数据同步。
数据库之间数据同步的方式:canal、slaveof、dblink、datax、脚本。