* 面试题:
* 1、假设保存菜品成功,保存redis失败,问是否应该回滚菜品的数据?<br /> * * 需要回滚,在点餐时菜品需要先在Redis中完成预扣,如果redis中没有当前的菜品,则无法完成预扣,菜无法售卖<br /> * 变化:假设保存的菜品的口味成功,保存到Redis失败,问是否应该回滚菜品分类的数据?<br /> * * 不需要,保存redis不会影响正常业务逻辑的执行<br /> *<br /> * 2、更新数据时,应该是先更新redis还是先更新数据库? 为什么? 双写一致性问题<br /> * * 先更新数据库,考虑redis和mysql的数据时刻保持一致
新增: 先保存mysql,在保存redis, 结合spring事务管理完成mysql回滚
修改: 先修改mysql,在修改 redis,
修改: 先删除mysql,在删除 redis,
https://blog.csdn.net/yulidrff/article/details/86296714
https://mp.weixin.qq.com/s/LqWiwzr1jdX0N9tAxw9gMQ
1.什么是超卖现象:
当前菜品库存只有1个,当有多个线程过来后,都执行成功了,生成了多个订单,这就是超卖。
跟本的原因是:
mysql的隔离级别:可重复读,会出现丢失跟新问题
2. 如何解决超卖问题? 库存
1. 3种方案:
- 利用mysql的悲观或者乐观锁加上版本号,版本号相同的话修改,不相同不修改(大量操作数据库对性能有影响)
- 分布式锁
使用Redisson的操作对象AOtomicLong预扣方案,保证数据库跟redis的双写一致性
2. 库存预扣方案(项目中使用的)
redis中库存:业务需要
- mysql库存:真正库存
- 时刻保证 mysql和redis库存一致 (双写一致性问题)
1、先将所有的菜品对应的库存保存到Redis, AtomicLong(key:dishId, vlaue:num)
2、更改数据库的库存之前,先去在redis 预扣
3、判断 redis中库存 >=0 库存足,可以扣减数据库库存, <0 库存不足,终止当前请求
3. 菜品的库存第二天如何更新?
- 创建菜品时会保存在redis跟mysql中,修改也会跟新redis跟mysql中
- 即使服务宕机,重启也会在redis中初始化,项目中@Comment跟@PostConstruct进行库存的初始化查询数据库
4. 更新菜品库存时为什么要加分布式锁?
操作库存:
1、点餐扣库存
2、 后台更新菜品的库存4.整个购物车操作的流程是什么?
5.购物车使用的是什么存储的? 你是怎么考虑的?-Redis 4个点
RMapCache。
Redis中:OrderItemVo
①MultiUtility 工具:Redis 支持“发布+订阅”的消息模式
②响应快速:redis存到缓存中,读取快,对购物车的操作频繁,分担mysql压力
③操作都是原子性的:高并发的时候,处理一些需要锁的业务
④支持7种数据类型,满足存储各种数据结构体的需要6.购物车数据类型是什么? key是什么? value是什么?
什么是联锁?
数据类型:Hash 主key:前缀+订单编号。辅key:菜品id(dishID) value:orderItemVo(订单明细)
通过RedissonMultiLock,实现联锁
总体而言,就是将 key1、key2、key3 …… keyN 放到一个 List 集合中,然后迭代循环加锁,直到所有的都成功。解锁的时候就是再遍历锁进行释放锁7.添加购物车为什么需要添加 菜品和订单 加联锁?
购物车本质就是修改菜品库存和更新订单。8.库存扣减的 时机?
常用两种库存扣减时机
下单时扣减库存
优点:
不会占有库存
缺点:
下单不一定可以买到菜品
加购物车扣减库存
优点:
下单一定可以买到菜品
缺点:
占用菜品库存,导致菜品滞销
延迟队列解决
如何选择思考
站在 消费者 角度考虑
加购物车扣库存
站在 商家 角度考虑
下单时扣减库存
站在两个角度,同时兼顾两者利益
场景
jd、淘宝
唯品会
恶意攻击问题
限制
前端
后端9.添加和移除购物车 如何保证库存的一致性?(MySQL和Redis双写一致性问题)
添加:先扣Redis库存判断是否成功,成功就扣除MySQL库存,失败将Redis库存加回去,
扣除MySQL库存是否成功,成功继续业务,失败MySQL回滚,Redis库存加回去。10.下单操作业务流程是什么?
11.购物车订单项 和 可核算订单项的合并逻辑?
查看购物车订单项是否为空,为空,不合并,直接返回,不为空判断购物车订单项和可核算订单项的菜品id是否相同,相同数量增加,不同直接创建新的可核算订单项,删除购物车订单项。
若有收获,就点个赞吧