秒杀项目常见问题+MQ
CAP理论:可用性、一致性、分区容错性三者最多能满足两个
一.秒杀系统架构(秒杀步骤)
1.等到秒杀时间,开放秒杀地址,进行秒杀,同时做相应的限流操作,减轻服务器压力 2.(通过HTTP接口发送秒杀请求)校验库存,内存标记+多级缓存 3.扣库存+创建用户订单, 4用户通过轮询等待消费者完成任务
二.防止超卖
1.通过内存标记,内存标记为空了之后不再处理后续请求,减轻redis缓存压力 2.redis进行预减库存,再通过MQ对数据库进行减内存和生成订单的操作 3.对mysql操作时利用行级锁,防止超卖; 4.同时给减库存和生成订单两个操作做一个事务,保证同时运行。遇到回滚就返回exception,事务的传播使用required,如果当前没有事务,就新建一个事务。
三.接口限流
几种限流措施(令牌桶限流,单用户访问频率限流、秒杀接口隐藏) 与漏桶算法相比,令牌桶算法更适合具有突发特性的流量。 令牌桶算法用Guava(谷歌开源的java工具类实现),使用非阻塞式
四.隐藏秒杀接口
在预缓存时就把后端的时间拿过来,开始倒计时,来保证前后端时间的一致 1.每次点击秒杀,会先从服务器获取一个秒杀验证值(接口判断是否到秒杀时间)(为了安全,验证值用加了盐值的MD5加密 2.redis增加缓存 key为用户加商品,value为缓存验证值 3.用户秒杀商品的时候要带上验证值
访问频率限制 一段时间访问次数写在redis里,超出不再服务
保证缓存和数据库的最终一致性 延时双删、旁路缓存 mysql若使用了主从模型也可以用延时双删 若删除失败还有失败重试机制(使用失败重试机制时为了防止对业务代码的入侵,可以通过订阅binlog日志写一段非业务代码,从binlog日志中取出要操作的树据,通过消息队列的方式进行删除缓存。
五.订单的异步处理
同步:大量请求同时请求导致数据库读写功能骤减 异步:一条条以顺序的方式写入数据库,连接数几乎不变
RabbitMq相关知识
解耦 异步 削峰
怎么解耦,怎么异步 怎么削峰
MQ的整体架构: 生产者-broker(交换机,根据所选择的模式根据routing或者binding把消息传给相应的消息队列,消费者从中取出进行消费)
RabbitMQ如何保证消息的可靠性
1.从生产者到消息队列,congfirm模式(与事务相比confirm模式最大的优势是异步)通过消息确认机制来保证,通过给每个指派唯一标志,完成消费后返回ack确认, 2 消息队列 消息队列的持久化,包括交换机持久化,消息队列持久化以及消息持久化 3.消费者 消费完返回完后手动ack确认,开启RabbitMQ会等待消费者显式发回ack信号后才从内存(和磁盘,如果是持久化消息的话)中移去消息。否则,RabbitMQ会在队列中消息被消费后立即删除它。 若长时间没有ack确认会像下一个消费者发送任务,同时需要做等幂性处理。
MQ分布式事务
补偿机制(消费失败后在投入队列,再不行进入死信队列) MQ解决分布式事务:采用最终一致性来结局 1、确认生产者一定要将数据投递到MQ服务器中(采用MQ消息确认机制) 2、MQ消费者消息能够正确消费消息,采用手动ACK模式,使用不补偿机制(注意重试幂等性问题) 3、如何保证第一个事务先执行,采用补偿机制(补单机制),在创建一个补单消费者进行监听,如果订单没有创建成功,进行补单。 ———————————————— 版权声明:本文为CSDN博主「gnui851016」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/gnui851016/article/details/93632128
常见分布式事务解决方案: 1.2PC 2.3PC 3.TCC 4.本地消息表 5.消息事务
登陆过程
1.使用手机号登陆,在前端密码先进行一次加固定盐值的MD5加密 2.验证手机号和密码格式 3.判断是否已经注册过(先从redis里找,再从表里找) 4.将得到的加密过的密码在通过一次MD5(盐值从数据库里获得,注册时随机生成),然后进行验证,通过就成功
分布式sesson过程
其他方法: 比如在每个服务器上session都复制一遍,springboot自带的分布式session等,前端存储等
通过redis完成分布式session
每次用户登陆的时候生成一个UUID(ticket),存到cookie里,同时在redis里生成相应的缓存(key:“user”+ticket,value:user(json形式)) 这样下次一定时间内不用登录,直接带着浏览器里的cookie去就能取得user信息。若判断相应的value值为null,再返回login界面。
写了个啥来着每次都能带着cookie?回去看看
MQ临时扩容,批量重导 (丢弃是丢到死信队列里去)