场景
搜小说 https://198200.com业务场景:下单时扣减库存,由于比较简单,商品和库存都放到了一个上下文中
学习多个上下文之间的交互,协作,订单上下文生成订单时,扣减商品上下文中的库存
第一个方法
第一个方法的技术选型,Redis,WebApiClient,EF CORE, Polly, ExceptionLess,雪花算法
把商品的库存放到redis中,在redis中验证库存,redis中扣减库存,生成订单后使用WebApiClient调用商品上下文中扣减库存的接口
问题:
1,在redis中验证库存,扣减库存时,需要加上Look,多线程时,获取redis中的库存时不加锁获取的库存可能不正确
2,确保WebApiClient调用接口能成功,使用polly 如果掉接口异常,失败时,重试,重试过程中记录异常,和重试的次数,并发出通知。
3,性能不强,EF core 需要持久化订单的数据,使用WebApiClient调用商品上下文中的接口有网络开销
4,WebApiClient请求异常,失败时,Polly会进行重试,出现多次调用的问题,商品上下文接口必须做幂等
5,如何保证不超卖,执行扣减库存修改语句是带上库存必须大于0的条件
第二个方法
第二个方法的技术选型,Redis,CAP,Rabbitmq,EF CORE, Polly,ExceptionLess,雪花算法
把商品的库存放到redis中,在redis中验证库存,redis中扣减库存,生成订单时开启事务,使用CAP来发送消息到EventBus,商品上下文订阅,扣减库存
问题:
1,如果保证消息不丢,使用CAP,CAP是基于本地消息表的方式来实现的组件,发送消息和消费消息都已本地事务的方式记录了发送和消费的情况,如果失败
会进行重试,重试一定的次数,可以人工干预解决问题,也可以做补偿事件,
2,订阅消息时可能出现异常,CAP会进行重试,同一消息会出现多次消费的问题,商品上下文接口必须做幂等
3,CAP在发送,消费消息时都会已本地事务的方式,写入一条信息到数据库表中,进行了2次IO的交付
第三个方法
第三个方法的技术选型,Redis,Rabbitmq,CAP,EF CORE, Polly,ExceptionLess,雪花算法
之前看过一句话,
读多写少用缓存,写多读少用队列
,我们可能使用队列来提高我们的处理能力,队列可以堆积消息,所以要使用消息队列
使用CommandService来发送Command,DomainEventService来发送事件,CAP具有EventBus的功能,但是多了2次IO的交互,使用自己简单封装Rabbitmq来写CommandService
事件会改变我们系统的状态,代表已经发生过的事实,比较重要,为了确保安全选择了CAP
当前端调用我们接口时在Controller中使用CommandService发送command到EventBus,commandHandler订阅消息,在redis中验证库存,redis中扣减库存,生成订单时开启事务
使用DomainEventService来发送消息到EventBus,商品上下文订阅,扣减库存
问题:
1,CommandService的实现,参考Rabbitmq官网的demo以及文档,参考CAP源码
2,使用队列后,没有获取到返回值,通过记录日志,查看消息的消费情况
3,大大增强了框架的复杂性,查错比较复杂
4,Rabbitmq没有使用集群,web也没有使用集群,数据没有集群,目前对于集群的学习比较浅