java - 高并发的后台如何处理数据库的更新与插入操作

 醒九九爷 发布于 2022-10-26 07:39

今天忽然想到一个问题
对于高并发条件下,后台对数据的更新和实例化是怎么进行的?

1、直接插入数据库,然后更新缓存?
这样这个更新操作将会有IO阻塞风险吧、

2、直接更新缓存,然后使用消息队列更新数据库?
只能延缓IO阻塞,并不能避免

3、直接更新缓存,定时批量更新数据库
这样IO的问题是解决了,但是数据在缓存里感觉很慌。

也没实践过真正的高并发系统,这种情况怎么解决?

----------补充----------

总结一下

就是已知直接插入和更新数据库将面临IO阻塞的风险,那么将数据最终实例化到数据库的过程是怎么样的。

7 个回答
  • 楼主的这个问题,普遍存在大部分的应用,并且这个和系统是否高并发关系不是很大,我以前也有思考过类似的问题
    浅谈缓存(二)
    首先说一下缓存,我们的程序在绝大部分情况下,对缓存其实应该是"弱依赖”的,怎么去理解这个“弱依赖”呢?
    我的理解是,我们的程序的数据的正确性在大部分情况下,都不会由缓存中的数据来判断,比如说"商品详情页商品的价格"其实就是缓存中的数据,但是我们在生成订单的时候的总价,必须要去数据库里面在查一遍.当然我说的是大部分情况,但是还有极少数情况下对数据正确性没那么严格(比如说抽象,安慰奖数量可以事先加载到缓存,后续业务需求可以直接通过缓存中的奖品数量来计算,因为根据一般业务,安慰奖都是一些对商家有利的附加比如说满100减5元,这个时候就算缓存挂掉,重新刷一遍对商家影响也是很小)

    那有没有办法,能保证数据库和缓存强一致性呢?在这个过程中就涉及到分布式事务,双方实现X/Open XA协议,但是redis目前还为实现该协议,并且由于在整个分布式中需要长时间锁资源,所以这种方式并不推荐使用(最终一致性还会有可能出现一段时间内数据不一致,这样会大大增加redis的复杂度)

    所以常用情况下,我们一般都是先保证数据库数据正确的情况下,同步/失效/异步去更新缓存

    2022-10-27 00:43 回答
  • 这个问题问的其实很好。
    如果是对于读操作,应该是没有问题的,因为对于目前大多的数据库,数据大多是写时才更新的(Copy on Write),因为现在的主流数据库大多已经能很好的在数据库层面的高并发支持并发读了,关键是对于写操作,怎么保证数据的一致性,在更新完数据的同时能保证缓存也被更新,这有数据库的ACID理论作为保证。
    对于写操作,现在互联网的数据库的ACID特别是一致性,谈的是数据的最终一致性,而不是传统的一致性,这样能保证用户的请求可以很快被响应。这个文章是一个CAP的介绍,http://blog.csdn.net/starxu85... 可供参考
    你的这个问题其实对应的场景就是“双十一”的秒杀,几千个人或更多去抢拍一个商品,如果数据库频繁的写,势必导致锁表、阻塞其他操作,所幸的是目前有些数据库针对这种场景做了性能优化(比如新开源的基于MySQL做了针对秒杀优化的AliSQL),可以在数据库的缓存中对这些请求做消息队列,然后一次更新,保证了高并发。当然中间有其他的理论支撑,比如高低水位、线程池等。
    以上是本人的一点拙见,本人也并非专业的DBA,如果有理论错误的话,也欢迎各位补充。

    2022-10-27 00:44 回答
  • 这问题比较大,不同场景下的高并发也是有不同的方案的。

    例如微博是高并发,金融系统也是高并发,前者就算发生信息丢失也问题不大,后者则对信息持久化有严格的要求。

    还有你这个是高并发读还是高并发写?

    是某时间段内高并发,还是持续性高并发?

    没有说明前提条件,让人怎么回答?

    2022-10-27 00:44 回答
  • 谢邀,但我对处理这个问题没啥经验,只能从理论上说说

    首先,加缓存是必然的,缓存的目录就是将处理不过来的东西暂存起来,延长等待时间。比如突然10分钟的高并发,引起需要处理的问题堆积,通过缓存,可以让这10分钟的内容在半个小时处理完。当然这里有一个假设,就是10分钟高并发后的时间里,没有太多需要处理的问题流入。

    那么问题来了,如果后面的流入速度仍然很高,根本处理不过来怎么办?最近刚好学了一个词,backpressure,背压,最到背压最直接的处理办法是丢弃一部分内容。当然对于数据来说,你肯定不想丢弃,那就只能从处理效率上去想办法,所以使用扩展、集群、分流等一大堆的并发处理技术

    以上都是个人理解,用的口水话,不够专业,仅供参考

    2022-10-27 00:45 回答
  • 先写入缓存,然后再持久化到磁盘中,楼主是担心缓存服务器挂了导致数据丢失?
    一般生产环境下无论是应用服务器、数据库服务器还是缓存服务器,都不会是也不应该是单机的,至少都是主从的结构,一台挂了还有另一台顶着,在负载正常的情况下,单台挂的是几率本身就不是很高,更何况是两台同时挂了,而类似Redis可以做集群,所以如果部署正常的话,这个问题出现的可能性相当低。
    楼主可以去了解一下CAP理论,根据你的描述你想要达到的效果和CAP阐述的是差不多的,没有绝对完美的方案。

    2022-10-27 00:45 回答
  • 写操作时无法直接避免的,如果你总在考虑“极端情况”那么就会忽略问题的重点。

    2022-10-27 00:45 回答
  • 中间池啊,cache啊,redis、反正就是这个意思;
    如果池都阻塞了,还是+处理单元吧;这就像樱桃小口小瘦子,吃一锅饭,用多大碗都不行,那就找十个樱桃小口小瘦子或者找个嘴敞的大胖子;

    更新:

    如果真的高并发的话,首先先确定高并发是持久还是偶尔暴涨的;
    1,如果暴涨的话,使用二级池还是可以缓解的;具体实现:应用=>redis=>数据库三层方式解决;一般推荐redis与数据库可或两台处理;应用一台;加一台分发+逆向代理或动静态分流;实现应用+数据的双层池;1*Reverse&HTTP+1*Redis+1*DataBase
    
    2,如果持久高并发,应结合您应用拓扑结构上,考虑使用集群从逻辑、应用层、分层降低单点的应用压力;具体实现:
        1,同大1,特点简单;1*Reverse+n*HTTP+n/y*Redis+N/x*DataBase+1*MainDataBase;
        2,应用模块化;单台服务为应用+数据库,前端使用逆向代理实现负载平衡,后端使用一台服务器实现全数据同步;特点,比较粗暴适合应用全部逻辑层都负载很平均都很高的情况;劣势是,可能为了适应负载点高部分,负载点低部分的性能会浪费掉;1*Reverse+n*Service+1*MainDataBase;
        3,根据应用的逻辑分层,例如用户+逻辑1+逻辑2+订单+论坛这种方法,每种逻辑一台服务器;这种分发需要比较细致、全面的负载测试;但是再次大规模拓容比较费力;而且需要很强的负载预估能力;具体实现同2,只是中间部分每台服务器仅负担应用单层负载;特点,可以很精确的适应应用;劣势是:忒复杂;1*Reverse+N*1Service+N*2Service+N*3Service...+N*Redis+N*DataBase+*MainDataBase;
        
        以上几种方法,个人认为应从实际出发选择适合自己的拓容方式;只有优劣选择,没有孰好孰坏;仅此...**楼歪了~怎么说道负载均衡了?**
    2022-10-27 00:46 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有