在 進入mq之前,就進行限流,采用令牌桶方法,這樣的話后續(xù)流量到達mq就會顯著減少
分庫分表:分庫字段以用戶字段或者訂單號,用戶的話可能會出現(xiàn)數(shù)據(jù)傾斜問題,有些用戶訂單很多,出現(xiàn)超大訂單問題按訂單號分的話可能導致不同的訂單分散在各個庫里,這樣的話通過訂單號做唯一索引進行防重就有問題了
分布式數(shù)據(jù)存儲問題可以分為:數(shù)據(jù)分片、數(shù)據(jù)復制、數(shù)據(jù)一致性binlog
1、statement 是記錄sql語句到blinlog? ? sql復雜度高時,解析需要大量精力,那么bug也就可能更多
2、row? 存放實體的變更前后的狀態(tài)? 不需要解析sql
3、mixed,動態(tài)選擇statement還是row模式寫入binlog時,binlog會使用ack機制進行穿行消費,每消費一條,確認一條(那么使用串行的話,消費效率就低,單線程無法水平擴展,架構(gòu)有缺陷)采用并行的方式。借用MQ進行拆分,在binlog處仍然串行消費,但是至少ack數(shù)據(jù),ack數(shù)據(jù)后發(fā)送到MQ里面的某個Topic即可,因為制作ack并轉(zhuǎn)發(fā)至MQ,不涉及業(yè)務(wù)邏輯,所以性能消費非常小,大概只有幾毫秒或者納秒 發(fā)后仍需要串行消費,比如上面提到的同一條微博的多次修改就需要串行消費,而多條微博間的修改則可以并行消費,它不存在并發(fā)問題。
判斷需要串行消費的數(shù)據(jù),比如同一條微博數(shù)據(jù),都會發(fā)送到 MQ 中間件的串行通道內(nèi)。在同步模塊進行同步時,MQ 中間件里的串行通道的數(shù)據(jù)均會串行執(zhí)行,而多個串行通道間則可以并發(fā)執(zhí)行。借助 MQ 中間件的此特性,既解決了亂序問題又保證了吞吐量。很多開源的 MQ 實現(xiàn)都具備此小節(jié)介紹的功能,如 Kafka 提供的 Partition 功能
多張表中使用分布式鎖,比如訂單和商品表均存儲了訂單號,當訂單信息或者商品信息發(fā)生變更時候,因為對訂單號進行加鎖沒在數(shù)據(jù)同步時候兩張表歸屬同一訂單號的數(shù)據(jù)實際為串行執(zhí)行。此方式所以可以解決redis和數(shù)據(jù)庫不一致問題,但是多張表加鎖又降低了吞吐量
采用反查的方法進行全量覆蓋,盡量反查binlog的從庫,保證主庫的性能
采用redis的hash結(jié)構(gòu)進行局部更新key為? 設(shè)計為訂單號+子表標識,如 Key 為 OrderId_BaseInfo,表示某一個訂單的基本信息,或者 Key 為 OrderId_SkuId,表示某一個訂單下的某個商品基本信息。在上述訂單案例的多張表變更時,同步程序無須對多張表間進行分布式加鎖協(xié)調(diào),哪張表變更就去更新緩存中對應(yīng)的局部信息即可。不管是同步性能還是實現(xiàn)難度均較好。
開發(fā)數(shù)據(jù)對比模塊,雖然binlog很多升級改造,但是也有可能導致數(shù)據(jù)不一致的情況,那么我們?yōu)榱吮WC數(shù)據(jù)的一致性,可以采用數(shù)據(jù)對比定期輪休比對數(shù)據(jù)庫和緩存,增加延遲重試,如果多次比對不一致的話,增肌報警,并保存當時的數(shù)據(jù),之后以數(shù)據(jù)庫中的數(shù)據(jù)為準刷新緩存延遲重試是為了防止因同步時差,出現(xiàn)短暫的數(shù)據(jù)不一致但數(shù)據(jù)最終一致性的情況,其次,保留出錯現(xiàn)場是為了排查定位問題
熱點問題查詢雖然單機的機器配置和程序是有上線的,但是可以進行節(jié)點間的主從復制,這樣不僅可以應(yīng)對查詢,而且可以做到高可用,以及開發(fā)進程應(yīng)用前置緩存,如何發(fā)現(xiàn)熱點數(shù)據(jù)呢,可以采用計數(shù)器,瞬時的流量只允許一個跑到后端,其他的直接返回,跑的那個負責拉取數(shù)據(jù)刷新到應(yīng)用內(nèi)存內(nèi)最后進行降級熔斷兜底,設(shè)置QPS為壓測的一半
如何保證寫入的時候無差錯,比如網(wǎng)絡(luò)中斷、CPU爆滿等等寫入的時候隨機寫入,并且按照權(quán)重值進行寫入,比如新加的數(shù)據(jù)庫一般容量大,優(yōu)先寫入新加入的數(shù)據(jù)庫。我們在寫入的時候可以維護一個可以用的列表,這樣在寫入的時候,如果發(fā)現(xiàn)數(shù)據(jù)庫故障,那么就把他從當前可用的數(shù)據(jù)庫列表中移除,如果大面積的數(shù)據(jù)庫都不可用,那么我們需要進行擴容,那么又如何維護可用的列表呢?可以通過人工感知的方式,寫服務(wù)的時候如果超過一半的認為掛了,那么就可以進行下線,下線的時候我們可以增加一個告警,因為下線的話是一個耗成本的事情,所以下線的時候可以設(shè)置一個告警,然后人工確認后再進行下線。
增加數(shù)據(jù)同步,當寫入成功后同步其他數(shù)據(jù)模塊,如立即刷新緩存
利用緩存+數(shù)據(jù)庫構(gòu)建高可用的扣減方案利用insert代替update,insert的庫稱為任務(wù)庫,存儲每次扣減的原始數(shù)據(jù),不做真實扣減,也即是不做uptate
數(shù)據(jù)校驗>開啟事務(wù)>扣減明細插入數(shù)據(jù)庫>進行緩存扣減>事務(wù)提交主要利用了數(shù)據(jù)庫順序?qū)懭胍雀滦阅芸斓倪@一特性
任務(wù)執(zhí)行可以參考一致性hash,交由到具體的worker進行執(zhí)行
扣減返還1、扣減完成后才能返還,必須攜帶扣減號,因為沒有扣減號,無法找到當前的扣減明細2、一次扣減可以多次返還
3、返還的數(shù)量要小于等于原始扣減的數(shù)量,需要多扣減ID進行加鎖,保證串行化執(zhí)行,因為返還的流量小所以可以使用加鎖的方法,來規(guī)避超賣的發(fā)生
4、保證接口的冪等性,可以通過數(shù)據(jù)庫設(shè)置唯一索引來防重,進而實現(xiàn)冪等性