搜尋

首頁  >  問答  >  主體

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

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

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

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

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

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

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

总结一下

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

大家讲道理大家讲道理2802 天前1315

全部回覆(7)我來回復

  • 天蓬老师

    天蓬老师2017-04-18 10:25:14

    中間池啊,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;
        
        以上几种方法,个人认为应从实际出发选择适合自己的拓容方式;只有优劣选择,没有孰好孰坏;仅此...**楼歪了~怎么说道负载均衡了?**

    回覆
    0
  • 黄舟

    黄舟2017-04-18 10:25:14

    寫操作時無法直接避免的,如果你總是考慮「極端情況」那麼就會忽略問題的重點。

    回覆
    0
  • 高洛峰

    高洛峰2017-04-18 10:25:14

    先寫入緩存,然後再持久化到磁碟中,樓主是擔心快取伺服器掛了導致資料遺失?
    一般生產環境下無論是應用伺服器、資料庫伺服器或快取伺服器,都不會是也不應該是單機的,至少都是主從的結構,一台掛了還有另一台頂著,在負載正常的情況下,單台掛的是幾率本身就不是很高,更何況是兩台同時掛了,而類似Redis可以做集群,所以如果部署正常的話,這個問題出現的可能性相當低。
    樓主可以去了解一下CAP理论,根据你的描述你想要达到的效果和CAP闡述的是差不多的,沒有絕對完美的方案。

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-18 10:25:14

    謝邀,但我對處理這個問題沒啥經驗,只能從理論上說說

    首先,加上快取是必然的,快取的目錄就是將處理不過來的東西暫存起來,延長等待時間。例如突然10分鐘的高併發,引起需要處理的問題堆積,透過緩存,可以讓這10分鐘的內容在半小時處理完。當然這裡有一個假設,就是10分鐘高併發後的時間裡,沒有太多需要處理的問題流入。

    那麼問題來了,如果後面的流入速度仍然很高,根本處理不過來怎麼辦?最近剛好學了一個詞,backpressure,背壓,最到背壓最直接的處理辦法是丟棄一部分內容。當然對於數據來說,你絕對不想丟棄,那就只能從處理效率上去想辦法,所以使用擴展、集群、分流等一大堆的並發處理技術

    以上都是個人理解,用的口水話,不夠專業,僅供參考

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-18 10:25:14

    這問題比較大,不同場景下的高並發也是有不同的方案的。

    例如微博是高並發,金融系統也是高並發,前者就算發生資訊遺失也問題不大,後者則對資訊持久化有嚴格的要求。

    還有你這個是高並發讀還是高並發寫?

    是某時段高並發,還是持續性高併發?

    沒有說明前提條件,讓人怎麼回答?

    回覆
    0
  • PHPz

    PHPz2017-04-18 10:25:14

    這個問題問的其實很好。
    如果是對於讀取操作,應該是沒有問題的,因為對於目前大多的資料庫,資料大多是寫時才更新的(Copy on Write),因為現在的主流資料庫大多已經能很好的在資料庫層面的高並發支援並發讀了,關鍵是對於寫入操作,怎麼保證資料的一致性,在更新完資料的同時能保證快取也被更新,這有資料庫的ACID理論作為保證。
    對於寫入操作,現在網路的資料庫的ACID特別是一致性,談的是資料的最終一致性,而不是傳統的一致性,這樣能保證使用者的請求可以很快被回應。這篇文章是CAP的介紹,http://blog.csdn.net/starxu85... 可供參考
    你的這個問題其實對應的場景就是「雙十一」的秒殺,幾千個人或更多去搶拍一個商品,如果資料庫頻繁的寫,勢必導致鎖表、阻塞其他操作,所幸的是目前有些資料庫針對這種場景做了性能優化(比如新開源的基於MySQL做了針對秒殺優化的AliSQL),可以在資料庫的快取中對這些請求做訊息佇列,然後一次更新,保證了高並發。當然中間有其他的理論支撐,像是高低水位、線程池等。
    以上是本人的一點拙見,本人也並非專業的DBA,如果有理論錯誤的話,也歡迎各位補充。

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-18 10:25:14

    樓主的這個問題,普遍存在大部分的應用,並且這個和系統是否高並發關係不是很大,我以前也有思考過類似的問題
    淺談緩存(二)
    首先說一下緩存,我們的程序在絕大部分情況下,對快取其實應該是"弱依賴」的,怎麼去理解這個「弱依賴」呢?
    我的理解是,我們的程式的資料的正確性在大部分情況下,都不會由快取中的資料來判斷,比如說"商品詳情頁商品的價格"其實就是快取中的資料,但是我們在產生訂單的時候的總價,必須要去資料庫裡面在查一遍.當然我說的是大部分情況,但是還有極少數情況下對數據正確性沒那麼嚴格(比如說抽象,安慰獎數量可以事先加載到緩存,後續業務需求可以直接通過緩存中的獎品數量來計算,因為根據一般業務,安慰獎都是一些對商家有利的附加比如說滿100減5元,這個時候就算緩存掛掉,重新刷一遍對商家影響也是很小)

    那有沒有辦法,能保證資料庫和快取強一致性呢?在這個過程中就涉及到分散式事務,雙方實現X/Open XA協定,但是redis目前還為實現該協定,並且由於在整個分散式中需要長時間鎖定資源,所以這種方式並不推薦使用(最終一致性還會有可能出現一段時間內數據不一致,這樣會大大增加redis的複雜度)

    所以常用情況下,我們一般都是先保證資料庫資料正確的情況下,同步/失效/異步去更新快取

    回覆
    0
  • 取消回覆