zoukankan      html  css  js  c++  java
  • 关于高并发问题的点滴思考

    问题背景:

    曾经做过一个项目,医院预约挂号系统,挂号的话专家号很多人抢,这是一个高并发的问题,我以前针对专家号系统的解决方案就是直接在数据库MySQL上面加锁,简单有效,完美完成任务,但是这是针对并发量很少的情况,最近在思考,如果并发量很大的话,我的专家号系统模块应该怎么办呢?


    专家号系统模块需要解决的问题:

    1.瞬间高并发(很多人在同一时间抢购专家号)

    2.超卖问题(防止出售超过库存数量的专家号)


    高并发问题的解决方案:

    提高系统的并发能力的方式主要有两种:垂直扩展和水平扩展,前者垂直扩展可以通过提升单机的硬件性能,或者提高单机的架构性能,来提高并发性,但是单机的性能总是有限的,所以高并发的终极解决方案还是水平扩展

    (以下方案为自己暂时可以想到的方法,可能不成体系)


    一.前端层设计(核心是请求拦截):

    1.对于抢专家号系统的那个页面的立即抢购按钮,设置为只能点击一次,避免用户重复点击导致不断发送请求

    2.限制一个用户在x秒之内只能发送一次抢购请求

    3.同一个IP在x秒之内只能提交一个抢购请求


    二.服务层设计(核心是充分利用缓存):

    1.使用线程池,降低线程建立和销毁的开销

    2.降低锁的粒度:为每个专家的专家号设置一个互斥锁,这样可以做到只有争抢同一个专家号的线程互斥,而不是所有线程互斥

    3.采用消息队列缓存请求:后台根据自己的能力,从消息队列中主动的拉取请求消息进行处理,这样可以拦截大量的并发请求

    4.用户请求预处理:如果所需的专家号没有了,那么就不用处理这个请求了,直接返回失败

    5.利用缓存对于读请求:因为大部分请求是读请求,所以可以利用缓存分担数据库压力

    6.利用缓存对于写请求:利用Redis作为中间件,把MySQL数据库中的专家号的那部分数据放入到Redis缓存中,所有的减少库存操作都在Redis中进行,然后再跟MySQL数据库进行数据同步


    三.数据库层设计(核心是数据库的优化):

    1.建立数据库链接池,降低数据库链接建立和销毁的开销

    2.数据库优化

        *SQL语句优化

        *索引优化

        *数据库表结构优化(合适的数据类型,遵循三大范式,表的拆分)

        *配置系统的优化(增加TCP支持的队列数,增加缓存池的大小和数量)

        *硬件优化:多核心的高主频CPU,大的内存,高性能的磁盘


    ps:还要一个最重要的,将专家号系统模块独立部署,避免该模块的高并发情况影响整个医院预约挂号系统的正常业务


    超卖问题的解决方案

    1.悲观锁:在一个线程修改数据的时候,采用锁定状态,排斥外部请求的修改

    2.FIF0队列:同一商品的请求放入同一队列中,串行处理

    3.乐观锁:采用带版本号的更新实现,也就是对这个数据而言所有的请求都有资格去修改,但是会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回失败


    总结:以上的策略都是自己暂时可以想到的,等知识完善了再过来填坑,抢专家号系统模块目前正在改进中!



  • 相关阅读:
    android 布局边框的使用,在xml文件中配置边框大小及颜色
    android去掉layout顶部的阴影(状态栏下边的阴影)
    ExpandableListView
    addTextChangedListener有错
    Android EditText____TextchangedListener
    LinkedHashMap.get("key")
    适配器模式(Java代码)
    单例模式(Java代码)
    工厂方法模式(Java代码)
    质数算法
  • 原文地址:https://www.cnblogs.com/yinbiao/p/10682535.html
Copyright © 2011-2022 走看看