高并发项目总结

如何解决超卖?少卖?

利用 Redis 的原子自增操作,

1
2
1.mysql锁机制,悲观锁InnoDB行级锁方案,思路是在数据库中设计一个状态标识位,用户在对数据进行修改前,将状态标识位标识为正在编辑的状态,这样其他用户要编辑此条记录时系统将发现有其他用户正在编辑,则拒绝其编辑的请求,类似于你在操作系统中某文件正在执行,然后你要修改该文件时,系统会提醒你该文件不可编辑或删除。不建议使用,对数据库压力较大,如果出现死锁会导致一直不能更新,除非kill掉进程
2.mysql乐观锁 不使用第三方情况下可以使用此方案,就是在数据库设计一个版本号的字段,每次修改都使其+1,这样在提交时比对提交前的版本号就知道是不是并发提交了,但是有个缺点就是只能是应用中控制,如果有跨应用修改同一条数据乐观锁就没办法了,这个时候可以考虑悲观锁

Redis预减成功而DB扣库存失败?

前面的方案中会出现一个少卖的问题。Redis在预减库存的时候,在初始化的时候就放置库存的大小,redis的原子减操作保证了多少库存就会减多少,也就会在消息队列中放多少。

现在考虑两种情况:

1)数据库那边出现非库存原因比如网络等造成减库存失败,而这时redis已经减了。

2)万一一个用户发出多个请求,而且这些请求恰巧比别的请求更早到达服务器,如果库存足够,redis就会减多次,redis提前进入卖空状态,并拒绝。不过这两种情况出现的概率都是非常低的。

两种情况都会出现少卖的问题,实际上也是缓存和数据库出现不一致的问题

但是我们不是非得解决不一致的问题,本身使用缓存就难以保证强一致性:

在redis中设置库存比真实库存多一些就行。

减库存然后下订单,但是服务器宕机?

改为先插订单,再去减库存,就是一个订单失效。保证用户无法自主生成orderid

插订单的时候加一个时间戳,利用Redis的过期时间设置

单用户订单存Hash,那一个用户下了很多单怎么办?

将uid_pid拼接成key,这样就可以由集群分摊流量,但是这样的缺点就是查询单用户的所有订单比较困难

Redis和数据库的一致性

一致性要求低可以使用两次删除

一致性要求高采用队列,并哈希至同一个工作线程

redis缓存与数据库一致性问题解决

redis系列之数据库与缓存数据一致性解决方案

应对高并发

浏览器部分

  • 浏览器缓存,减少请求
  • 一个域名能打开的链接就那么些,多个子域名部署,图片文件独立服务器减少请求数据量
  • 减少浏览器cookie大小

服务器部分:

Nginx

  • 应用集群,负载均衡
  • 分布式缓存+应用本地缓存
  • jvm 参数调优,像tomcat优化
  • 消息队列

数据库部分:

  • 数据库设计优化,SQL优化
  • 分库分表
  • 读写分离

流量削峰:

有两种:丢弃用户和不丢弃用户

不丢弃有排队(通过队列把同步变异步),答题,分层过滤(漏斗模型