(1)数据库高并发

        数据库高并发现象带来问题:数据库作为一个共享资源,应该能够供多个用户同时使用,当多个用户并行的存取数据库时,会发生多个用户程序并发的存取同一数据的现象,比如每天有上亿的流量对数据库进行操作,每秒并发读是几万次,每秒只要有数据更新,就可能会出现缓存与数据库数据不一致的问题,因此如果对并发操作不加控制可能会存取或存储不正确的数据,破坏数据库的一致性,因此对数据库的管理必须提供并发机制。带来问题:(1)丢失更新:当两个或多个程序读入同一数据并进行更改,由于线程运行时间的不确定性,可能会产生后一程序的更新结果被前一程序的更新结果覆盖;(2)读取“脏数据”:当一个程序修改数据库某一数据后,另一个程序对该数据进行了读取,由于某种原因,前一程序撤销了对数据的修改,那么后一程序读到的数据与本应读到的数据不一致,称为读取到“脏数据”;(3)不可重复读: A用户读取数据,随后B用户读出该数据并进行更改,此时A用户再读取数据发现前后两次的值不一致。

        数据库高并发解释:使用正确的方式调度并发操作,使一个用户事物的执行不受其他事物的干扰,从而避免造成数据的不一致性。

        数据库高并发现象解决方案:(1)添加Redis缓存数据库;(2)使用存储过程处理单个请求需要多次数据库访问,只需要将操作集成到存储过程中进行单个数据库的访问;(3)主从数据库读写分离,在主服务器上写入,在从服务器上读取,使用数据库复制将事物的删除、修改操作更新同步到集群中的从数据库;(4)分表分库,对于访问频率极高,数据流巨大的单个表,首先要做的就是减少单个表的记录数,减少数据查询所需要时间,提高数据库的吞吐量(水平分割),要选取适当的拆分策略;如果数据库主服务器面临高度并发的读写访问,划分数据库,可以提高数据库的写入能力(垂直分割);(5)负载均衡集群:将多个请求分担给多个处理节点,单个处理节点故障不会影响整个服务。

(2)消息总线高并发

        消息总线概念:所谓总线,就是像主板里的数据总线一样, 具有数据的传递和交互能力,各方不直接通信,使用总线作为标准通信接口。消息总线就是当消息更新时,通过消息中间件,使用消息广播的方式通知所有微服务节点同步更新数据。

        消息队列:是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。是一个专门处理消息的服务器或中间件,接收消息,(存储消息),分发消息。

        异步通信:注册时的短信、邮件通知,减少响应时间;

        应用解耦:信息发送者和消息接受者无需耦合,比如调用第三方;

        流量削峰:例如秒杀系统;

        消息总线常见的设计模式:

        P2P模式:包含三个角色(消息队列、生产者、消费者),每个消息都被发送到一个特定的队列,消费者从队列中获取消息,队列保留着消息,直到他们被消费或者超时,每个消息只有一个消费者,生产者与消费者在时间上没有依赖性。

        订阅/发布模式:包含三个角色(主题、发布者、订阅者),多个发布者将消息发布到对应的主题,系统将消息传递给多个订阅者,主题使得消息订阅者和发布者保持相互独立,不需要接触可保证消息的传递。

        消息总线优点:(1)实时性高:生产者无需等待处理结果,实现了异步处理;(2)生产者与消费者解耦;在消息总线中,生产者负责将消息发送到队列中,而消费者把消息从队列中取出来。生产者无须等待消费者启动,消费者也无须关心生产者是否已经处于就绪状态。所以,这种模式能很好地实现生产者与消费者的解耦;(3)故障率低:生产者与消费者之间不存在强关联关系,即便是生产者或消费者任意一方掉线了,也不会影响消息最终的送达;另一方面,消息总线往往会结合数据库来实现消息的持久化,并设置状态标识,只有消息消费成功,才会去修改状态标识;(4)消息总线同时还承担着缓冲区的作用。大量业务消息首先会进入消息队列进行缓存,消息的消费者可以根据自己的处理能力来进行消费,所以不管消息的数据量有多少,都不会对消费者造成冲击。

(3)典型应用案例

        在12306抢票系统、学生选课系统、秒杀系统等都会出现在短时间内产生大量流量(高并发),系统负载压力大。

        对于此高并发问题的解决方案

        对于数据库的设计:为了得到高性能,可以使用分表或者分库的设计,对于分表,由于存储数据多会造成查询和统计的缓慢,可以用多个表存储(查询时判定路由条件就可以得到对应的表);对于分库,将表数据存储在不同的数据库中,对分库数据进行查询时需要先由路由算法确定数据在哪个数据库中。(也可以通过redis缓存、建立索引、主从读写分离等方法来优化数据库的性能);

        对于消息总线: 系统通过消息总线来实现不同模块(抽象)之间的通信,比如当存在多个用户进行并发的登录系统时,消息总线将用户的请求置入消息队列中,异步的进行响应。比如拆红包的过程,红包系统生成一个红包,接下来这个红包的所有发红包、抢红包、拆红包等操作,红包系统是资金交易系统,DB 操作的事务性无法避免,所以会存在“并发抢锁”问题。但是如果到达 DB 的事务操作(也即拆红包行为)不是并发的,而是串行的,就不会存在“并发抢锁”的问题了。这就使用了消息总线处理并发问题,可以采用先进先出的方式排队拆红包。