聊聊商城那些事
今天我们来聊聊商城那些事
1. 如何保证请求数据不被恶意篡改(http://www.shop.cn/?type=cancel&orderId=1)
调用接口返回的参数为秘文,对用户没有意义,然后前端拿到加密后的参数再请求服务端,参数的加解密都在服务端,无法破解
- 连接拼接一段本url参数加密过的串,只修改参数值,不修改不知道加密算法也无法校验通过
http://www.shop.cn/?type=cancel&orderId=2019 - 参数按照固定方式排序、拼接、加密 token = md5(2019cancel)
- 加密后的内容拼接到链接中:
http://www.shop.cn/?type=cancel&orderId=2019& token = md5(2019cancel)
2. 购物车修改商品数量时,每次增加商品是否需要请求服务端,如果不请求,应该怎么做?
- 不应该请求服务端,购物车页面每个商品先返回一次最大数量,保证用户购物车数量不能大于当前数量(若校验)
- 提交生成订单的时候再做一次校验(强校验)
3. 生成订单过程中如何控制幂等性(如何区分用户是同一个商品下了两笔订单 还是 因为网络波动前端把生成订单的接口)
- 同样的商品下两笔订单,时间戳是不同的
- 同样的请求发送两次所有参数相同
4. 单个商品生成订单时,如何保证不超卖
4.1 悲观锁
select * from good where good_id = 1 for update;
这种情况下如果good_id有索引就是行锁,所有需要修改该条记录的操作都要进行排队操作,直到加锁的线程提交(commit)了本次操作
4.2 乐观锁
select good_count, version from good where good_id = 1;
假设查询结果为 good_count=100, version=1.0
然后通过程序计算本次购买3个后剩余库存为 100 - 3 = 97;
最后进行更新操作:
update good set good_count = 97, version = version + 0.1 where version = 1.0;
当别的线程操作了该条记录,那version值为1.1,进行更新操作的时候where条件就匹配不到
4.3自旋锁
乐观锁操作失败的情况下,再进行重试
4.4 redis
库存放在redis里面,然后通过原子操作去增加/减少库存(incr/incrBy/decr/decrBy),
同时再操作数据库.当流量增大时,进行服务降级,把同步数据库改为发送mq消息,消费端异步扣减库存并实例化到数据库中.
4.5 数据库
更新库存的时候加条件判断即可,假设当前库存为m,购买数量为n,则sql语句这样编写:
update good set count = count - n where count >= n;
5. 购物车生成订单时,如何保证不超卖
类似第4个问题,不过此处要加入联锁的概念:联锁表示当多个锁都成功都成功的时候,才算该锁加锁成功.在该问题中表示多件商品都判断库存足够时才能算下单成功.
悲观锁:购物车中所有都商品都锁库存依次去扣减并生成订单再释放锁.
乐观锁:依次扣除库存,当某一件商品扣除失败都时候,再恢复前面扣除的库存的商品.
6. 联合支付时如何保证积分不超卖
微信支付分为三阶段:
生成订单号
唤起支付
支付回调(只有当支付成功时,微信才会通知你,并且保证15s内一定通知一次/30s内一定通知二次/60s内一定通知三次)
未支付的订单固定时间后取消来释放积分
每次生成新订单时,查询数据库有没有未成功的订单后再去请求微信接口查询这些订单的实际状态,如果为未支付,则调用微信接口取消订单,如果取消成功回滚积分即可,如果取消失败,表示该笔订单可能再查询和取消的过程中被支付,根据微信返回信息再进行判断
7. 如何做一个商品秒杀方案
限流:
nginx:
tomcat:
acceptCount: 如果tomcat的线程都忙于相应,新来的会排队,如果超出排队大小,超出拒绝连接
maxConnections: 瞬时最大连接数,超出会排队等待
maxThreads: tomcat请求处理的最大线程数
算法:
漏桶算法
令牌桶算法
分片/分段(一致性哈希),库存放在redis里面进行原子操作,控制总数不会超过销售量,具体业务通过一致性哈希分到不同的“分片”中进行操作
进行具体业务操作,操作失败会滚库存
以上分享,大家有哪些收获或者疑惑吗?欢迎留言交流~!
干货满满,赞一个~