<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          springboot第60集:架構(gòu)師萬字挑戰(zhàn),一文讓你走出微服務(wù)迷霧架構(gòu)周刊

          共 10865字,需瀏覽 22分鐘

           ·

          2024-04-11 01:41

          提交退款申請后,通過調(diào)用該接口查詢退款狀態(tài)。退款有一定延時,用零錢支付的退款20分鐘內(nèi)到賬,銀行卡支付的退款3個工作日后重新查詢退款狀態(tài)。

          注意:如果單個支付訂單部分退款次數(shù)超過20次請使用退款單號查詢

          如果該訂單支付時間超過一年半,需單獨使用微信訂單號查詢或者同時使用微信訂單號和微信退款單號查詢

          3ed23ad3d5d574e1aae47a209ef12abd.webpimage.png 25189a71216dfa65a45df6bdf32d5678.webpimage.png

          當一個訂單部分退款超過10筆后,商戶用微信訂單號或商戶訂單號調(diào)退款查詢API查詢退款時,默認返回前10筆和total_refund_count(訂單總退款次數(shù))。商戶需要查詢同一訂單下超過10筆的退款單時,可傳入訂單號及offset來查詢,微信支付會返回offset及后面的10筆,以此類推。當商戶傳入的offset超過total_refund_count,則系統(tǒng)會返回報錯PARAM_ERROR。

          舉例:

          一筆訂單下的退款單有36筆,當商戶想查詢第25筆時,可傳入訂單號及offset=24,微信支付平臺會返回第25筆到第35筆的退款單信息,或商戶可直接傳入退款單號查詢退款

          當交易發(fā)生之后一段時間內(nèi),由于買家或者賣家的原因需要退款時,賣家可以通過退款接口將支付款退還給買家,微信支付將在收到退款請求并且驗證成功之后,按照退款規(guī)則將支付款按原路退到買家賬號上。

          注意:

          1、交易時間超過一年的訂單無法提交退款

          2、微信支付退款支持單筆交易分多次退款,多次退款需要提交原支付訂單的商戶訂單號和設(shè)置不同的退款單號。申請退款總金額不能超過訂單金額。 一筆退款失敗后重新提交,請不要更換退款單號,請使用原商戶退款單號

          3、請求頻率限制:150qps,即每秒鐘正常的申請退款請求次數(shù)不超過150次

          4、每個支付訂單的部分退款次數(shù)不能超過50次

          5、如果同一個用戶有多筆退款,建議分不同批次進行退款,避免并發(fā)退款導(dǎo)致退款失敗

          6、申請退款接口的返回僅代表業(yè)務(wù)的受理情況,具體退款是否成功,需要通過退款查詢接口獲取結(jié)果。

          7、一個月之前的訂單申請退款頻率限制為:5000/min

          8、同一筆訂單多次退款的請求需相隔1分鐘

          當用戶掃碼支付成功之后,微信會異步回調(diào)商戶接口,告知用戶支付成功。

          用戶支付成功后,微信異步通知商戶支付結(jié)果,商戶收到通知后告知支付通知接收情況。

          04f8173de96e26a0d39d7d7743195d98.webpimage.png

          有關(guān)商戶接口應(yīng)注意以下幾點:

          (1)該鏈接是通過【統(tǒng)一下單API】中提交的參數(shù)notify_url設(shè)置,如果鏈接無法訪問,商戶將無法接收到微信通知。

          (2)notify_url不能有參數(shù),外網(wǎng)可以直接訪問,不能有訪問控制(比如必須要登錄才能操作)。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”

          (3)支付完成后,微信會把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理,并返回應(yīng)答。

          (4)對后臺通知交互時,如果微信收到商戶的應(yīng)答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不

          保證通知最終能成功。(通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)注意:同樣的通知可能會多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理

          重復(fù)的通知。推薦的做法是,當收到通知進行處理時,首先檢查對應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過,如果沒有處理過再進行處理,如果處理過直接返回結(jié)果成功。

          在對業(yè)務(wù)數(shù)據(jù)進行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。

          (5)特別提醒:商戶系統(tǒng)對于支付結(jié)果通知的內(nèi)容一定要做簽名驗證,防止數(shù)據(jù)泄漏導(dǎo)致出現(xiàn)“假通知”,造成資金損失。

          8f78176cee256bfeb3f1612488a8a513.webpimage.png

          有關(guān)商戶接口應(yīng)注意以下幾點:

          (1)該鏈接是通過【統(tǒng)一下單API】中提交的參數(shù)notify_url設(shè)置,如果鏈接無法訪問,商戶將無法接收到微信通知。

          (2)notify_url不能有參數(shù),外網(wǎng)可以直接訪問,不能有訪問控制(比如必須要登錄才能操作)。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”

          (3)支付完成后,微信會把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理,并返回應(yīng)答。

          (4)對后臺通知交互時,如果微信收到商戶的應(yīng)答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不

          保證通知最終能成功。(通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)注意:同樣的通知可能會多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理

          重復(fù)的通知。推薦的做法是,當收到通知進行處理時,首先檢查對應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過,如果沒有處理過再進行處理,如果處理過直接返回結(jié)果成功。

          在對業(yè)務(wù)數(shù)據(jù)進行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。

          (5)特別提醒:商戶系統(tǒng)對于支付結(jié)果通知的內(nèi)容一定要做簽名驗證,防止數(shù)據(jù)泄漏導(dǎo)致出現(xiàn)“假通知”,造成資金損失。

          回調(diào)微信統(tǒng)一下單接口,獲取codeurl方法主要邏輯

          微信官方統(tǒng)一下單接口文檔說明: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

          (1)  根據(jù)接口需求添加所需參數(shù):比如appid,mch_id,body等等......

          (2)sign簽名獲取:具體獲取規(guī)則官方已經(jīng)說明: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3

          (3) 通過工具類將map集合轉(zhuǎn)為xml格式字符串

          (4)回調(diào)微信統(tǒng)一下單接口,接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder

          (5)如果上一步成功(成功標志返回SUSSCUSS),則將返回成功的xml格式再通過工具類轉(zhuǎn)為map

          (6)通過key=code_url,獲取value字符串,這也是最終生成二維碼的字符串。code_url格式大致為:weixin://wxpay/s/An4baqw

          接下來只要將code_url值變成二維碼就可以供用戶掃碼付款了。

          主要業(yè)務(wù)邏輯是:

          (1)通過商品ID查詢是否有該商品信息

          (2)通過用戶ID查詢是否存在該用戶

          (3)如果上面兩步?jīng)]有問題,則生成用戶訂單信息保存到數(shù)據(jù)庫中

          調(diào)用http://localhost:8081/api/v1/order/buy?video_id=1接口

          成功返回二維碼:code_url有效期是兩個小時

          (1)、post方式提交

          (2)、xml格式的協(xié)議

          (3)、簽名算法MD5

          (4)、接口交易單位為 分

          (5)、交易類型:JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付

          (6)、商戶訂單號規(guī)則:

          商戶支付的訂單號由商戶自定義生成,僅支持使用字母、數(shù)字、中劃線-、下劃線_、豎線|、星號*這些英文半角字符的組合,請勿使用漢字或全角等特殊字符,

          微信支付要求商戶訂單號保持唯一性

          (7)、安全規(guī)范:

          簽名算法:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3

          校驗工具:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=20_1

          (8)、采用微信支付掃碼模式二(不依賴商戶平臺設(shè)置回調(diào)url)

          9d9dd9d8c904c7123f5c324aa771b290.webpimage.png 62a1c550ffe4e1dcd37b70f439ebeff8.webpimage.png

          商戶后臺系統(tǒng)先調(diào)用微信支付的統(tǒng)一下單接口,微信后臺系統(tǒng)返回鏈接參數(shù)code_url,商戶后臺系統(tǒng)將code_url值生成二維碼圖片,用戶使用微信客戶端掃碼后發(fā)起支付。注意:code_url有效期為2小時,過期后掃碼不能再發(fā)起支付。

          25d26cbd2c5bca936cc8d016ed380991.webpimage.png 4ccb33558aba707a327bd829ddff5fab.webpimage.png 0cb4f41f7a1be533f9cd1a1f2218d78a.webpimage.png 195186390d8a9b2ffcd8057baf81f554.webpimage.png 1cd9c85f4e3692764193c6fd75e8a725.webpimage.png 140c2ac1eec46cdf309631ba6a6d5c77.webpimage.png

          微信支付申請審核通過后,商戶在申請資料填寫的郵箱中收取到由微信支付小助手發(fā)送的郵件

          ee4f3278f965c9540d5f44168a1b2af3.webpimage.png d6781ccf95c087a5cb30a28f5b6d24fb.webpimage.png 516461796d3159e2f536f5f32f6678f8.webpimage.png 6f921db2bc77b130faa065baf533a691.webpimage.png e5e1d7e2aee197cbafdbd35f5f1bd493.webpimage.png 624ffbb88c02ba5f377804349067d3a0.webpimage.png 394befaee2765a762573ed530bafdff9.webpimage.png a2df125cd11939148bb64b19b19edc5d.webpimage.png 338d32792046080d9ceca8bd223a9380.webpimage.png 312cd75d0b447ee2c56e5b61d692836e.webpimage.png e8cd13256fcf36445dfba1335e346e2c.webpimage.png e672227e483cbceabdcafd1fa2f8ab3d.webpimage.png 4c031542e85840d09e2089a5b99e1301.webpimage.png

          項目的質(zhì)量目標:

          1. 通過系統(tǒng)呈現(xiàn)的小程序或網(wǎng)站實現(xiàn)企業(yè)建設(shè)的各區(qū)域新能源管理,能夠遠程啟動充電,強制停止,功率限制等控制指令;
          2. 能夠自行分析新能源運營情況;
          3. 從多個統(tǒng)計維度,特征指標來分析新能源收入的分布和變化規(guī)律;
          4. 全面地了解企業(yè)整體營收情況

          場景 為了防止我們的接口被人惡意訪問,比如有人通過JMeter工具頻繁訪問我們的接口,導(dǎo)致接口響應(yīng)變慢甚至崩潰,所以我們需要對一些特定的接口進行IP限流,即一定時間內(nèi)同一IP訪問的次數(shù)是有限的。

          實現(xiàn)原理 用Redis作為限流組件的核心的原理,將用戶的IP地址當Key,一段時間內(nèi)訪問次數(shù)為value,同時設(shè)置該Key過期時間。

          比如某接口設(shè)置相同IP10秒內(nèi)請求5次,超過5次不讓訪問該接口。

          這是一個使用 MyBatis 的 XML 配置文件,用于映射數(shù)據(jù)庫表 tab_user 到 Java 對象 com.da.entity.User。

          以下是這個 XML 配置文件的主要部分:

          1. mapper 標簽: 定義了命名空間為 com.da.mapper.UserMapper,用于映射數(shù)據(jù)庫操作。
          2. resultMap 標簽: 定義了查詢結(jié)果的映射規(guī)則,指定了從數(shù)據(jù)庫查詢結(jié)果到 com.da.entity.User 對象屬性的映射關(guān)系。
          3. sql 標簽: 定義了一個 SQL 片段,名為 Base_Column_List,用于提供表的列名列表,可以在后續(xù)的 SQL 語句中重復(fù)使用。
          4. select 標簽: 定義了一個查詢語句,id 為 selectAll,執(zhí)行該語句會查詢 tab_user 表中的所有列,并將結(jié)果映射為 com.da.entity.User 對象。
          5. insert 標簽: 定義了一個插入語句,id 為 insert,用于向 tab_user 表中插入數(shù)據(jù),參數(shù)類型為 com.da.entity.User,并指定了插入的列和值。

          這個 XML 配置文件的作用是提供了 MyBatis 操作數(shù)據(jù)庫的映射規(guī)則和 SQL 語句,使得開發(fā)者可以通過調(diào)用對應(yīng)的方法來執(zhí)行數(shù)據(jù)庫操作,而不必編寫繁瑣的 SQL 語句。

          注意 ShardingSphere并不支持CASE WHEN、HAVING、UNION (ALL)有限支持子查詢。這個官網(wǎng)有詳細說明。

          實現(xiàn)分表

          c68448fd66e2e7237dc92f2c80425dfc.webpimage.png

          有個member庫,里面的tab_user表由一張拆分成3張,分別是tab_user0、tab_user1、tab_user2。

          如果表的數(shù)據(jù)過大,我們可能需要把一張表拆分成多張表,但不分庫。

          9367fa01aba38f2b8b2fd9562e8cad2d.webpimage.png

          Mysql是 Master-Slave (主從)部署的,那么數(shù)據(jù)保存到Master庫,Master庫數(shù)據(jù)同步數(shù)據(jù)到Slave庫,數(shù)據(jù)讀取到Slave庫,

          這樣可以減緩數(shù)據(jù)庫的壓力。同一個服務(wù)器建立兩個庫,一個當做Master庫,一個當做Slave庫。

          8017c95f00028f0ff77e92973e3b7aa8.webpimage.png

          通過分數(shù)進行排序的示例圖。 圖中展示了3張表返回的數(shù)據(jù)結(jié)果集,每個數(shù)據(jù)結(jié)果集已經(jīng)根據(jù)分數(shù)排序完畢,但是3個數(shù)據(jù)結(jié)果集之間是無序的。

          將3個數(shù)據(jù)結(jié)果集的當前游標指向的數(shù)據(jù)值進行排序,并放入優(yōu)先級隊列,t_score_0的第一個數(shù)據(jù)值最大,t_score_2的第一個數(shù)據(jù)值次之,t_score_1的第一個數(shù)據(jù)值最小,

          因此優(yōu)先級隊列根據(jù)t_score_0,t_score_2和t_score_1的方式排序隊列。

          af319a16e94cad7604ac37fd81880eea.webpimage.png

          展現(xiàn)了進行next調(diào)用的時候,排序歸并是如何進行的。 通過圖中我們可以看到,當進行第一次next調(diào)用時,排在隊列首位的t_score_0將會被彈出隊列,并且將當前

          游標指向的數(shù)據(jù)值(也就是100)返回至查詢客戶端,并且將游標下移一位(90)之后,重新放入優(yōu)先級隊列。根據(jù)當前數(shù)值,t_score_0排列在隊列的最后一位。 之前隊列中

          排名第二的t_score_2的數(shù)據(jù)結(jié)果集則自動排在了隊列首位。

          在進行第二次next時,只需要將目前排列在隊列首位的t_score_2彈出隊列,并且將其數(shù)據(jù)結(jié)果集游標指向的值返回至客戶端,并下移游標,繼續(xù)加入隊列排隊,以此類推。

          當一個結(jié)果集中已經(jīng)沒有數(shù)據(jù)了,則無需再次加入隊列。

          c2612dfc826c843c5c2fcb8503416996.webpimage.png

          可以看到,ShardingSphere的排序歸并,是在維護數(shù)據(jù)結(jié)果集的縱軸和橫軸這兩個維度的有序性。

          縱軸是指每個數(shù)據(jù)結(jié)果集本身,它是天然有序的,它通過包含ORDER BY的SQL所獲取。

          橫軸是指每個數(shù)據(jù)結(jié)果集當前游標所指向的值,它需要通過優(yōu)先級隊列來維護其正確順序。 每一次數(shù)據(jù)結(jié)果集當前游標的下移都需要將該數(shù)據(jù)結(jié)果集重新放入優(yōu)先級隊列排序,

          而只有排列在隊列首位的數(shù)據(jù)結(jié)果集才可能發(fā)生游標下移的操作。

          將從各個數(shù)據(jù)節(jié)點獲取的多數(shù)據(jù)結(jié)果集,組合成為一個結(jié)果集并正確的返回至請求客戶端,稱為結(jié)果歸并。

          我們在實現(xiàn)分庫分表之后,遍歷、排序、分組、分頁 和 聚合 操作變成不在一張表上進行SQL,而是多張表執(zhí)行的結(jié)果進行歸并。

          它是最為簡單的歸并方式。 只需將多個數(shù)據(jù)結(jié)果集合并為一個單向鏈表即可。在遍歷完成鏈表中當前數(shù)據(jù)結(jié)果集之后,將鏈表元素后移一位,繼續(xù)遍歷下一個數(shù)據(jù)結(jié)果集即可。

          由于在SQL中存在ORDER BY語句,每個數(shù)據(jù)結(jié)果集自身是有序的,所以我們要做的就是對多個有序的數(shù)組進行排序

          ShardingSphere在對排序的查詢進行歸并時,將每個結(jié)果集的當前數(shù)據(jù)值進行比較(通過實現(xiàn)Java的Comparable接口完成),并將其放入優(yōu)先級隊列

          每次獲取下一條數(shù)據(jù)時,只需將隊列頂端結(jié)果集的游標下移,并根據(jù)新游標重新進入優(yōu)先級排序隊列找到自己的位置即可。

          分組歸并的情況最為復(fù)雜,它分為流式分組歸并內(nèi)存分組歸并。 流式分組歸并要求SQL的排序項與分組項的字段以及排序類型(ASC或DESC)必須保持一致,否則只能

          通過內(nèi)存歸并才能保證其數(shù)據(jù)的正確性。

          舉例

          假設(shè)根據(jù)科目分片,表結(jié)構(gòu)中包含考生的姓名(為了簡單起見,不考慮重名的情況)和分數(shù)。通過SQL獲取每位考生的總分,可通過如下SQL:

                
                SELECT name, SUM(score) FROM t_score GROUP BY name ORDER BY name;

          在分組項與排序項完全一致的情況下,取得的數(shù)據(jù)是連續(xù)的,分組所需的數(shù)據(jù)全數(shù)存在于各個數(shù)據(jù)結(jié)果集的當前游標所指向的數(shù)據(jù)值,因此可以采用流式歸并。

          dc89ecaad3853579ca7b84deae53e420.webpimage.png

          進行歸并時,邏輯與排序歸并類似。 下圖展現(xiàn)了進行next調(diào)用的時候,流式分組歸并是如何進行的。

          6d3244308626954950965c8da5dee984.webpimage.png 6d3244308626954950965c8da5dee984.webpimage.png

          無論是流式分組歸并還是內(nèi)存分組歸并,對聚合函數(shù)的處理都是一致的。 除了分組的SQL之外,不進行分組的SQL也可以使用聚合函數(shù)。 因此,聚合歸并是在之前介紹的歸并類

          的之上追加的歸并能力,即裝飾者模式。聚合函數(shù)可以歸類為比較、累加和求平均值這3種類型

          比較類型的聚合函數(shù)是指MAXMIN。它們需要對每一個同組的結(jié)果集數(shù)據(jù)進行比較,并且直接返回其最大或最小值即可。

          累加類型的聚合函數(shù)是指SUMCOUNT。它們需要將每一個同組的結(jié)果集數(shù)據(jù)進行累加。

          求平均值的聚合函數(shù)只有AVG。它必須通過SQL改寫的SUMCOUNT進行計算

          所有歸并類型都可能進行分頁。 分頁也是追加在其他歸并類型之上的裝飾器,ShardingSphere通過裝飾者模式來增加對數(shù)據(jù)結(jié)果集進行分頁的能力。 分頁歸并負責(zé)

          將無需獲取的數(shù)據(jù)過濾掉。

          ShardingSphere的分頁功能比較容易讓使用者誤解,用戶通常認為分頁歸并會占用大量內(nèi)存。 在分布式的場景中,將LIMIT 10000000, 10改寫為LIMIT 0, 10000010,

          才能保證其數(shù)據(jù)的正確性。 用戶非常容易產(chǎn)生ShardingSphere會將大量無意義的數(shù)據(jù)加載至內(nèi)存中,造成內(nèi)存溢出風(fēng)險的錯覺。 其實,通過流式歸并的原理可知,會將

          數(shù)據(jù)全部加載到內(nèi)存中的只有內(nèi)存分組歸并這一種情況。 而通常來說,進行OLAP的分組SQL,不會產(chǎn)生大量的結(jié)果數(shù)據(jù),它更多的用于大量的計算,以及少量結(jié)果產(chǎn)出的場景。

          除了內(nèi)存分組歸并這種情況之外,其他情況都通過流式歸并獲取數(shù)據(jù)結(jié)果集,因此ShardingSphere會通過結(jié)果集的next方法將無需取出的數(shù)據(jù)全部跳過,并不會將其存入內(nèi)存。

          但同時需要注意的是,由于排序的需要,大量的數(shù)據(jù)仍然需要傳輸?shù)絊hardingSphere的內(nèi)存空間。 因此,采用LIMIT這種方式分頁,并非最佳實踐。 由于LIMIT并不能通過索引

          查詢數(shù)據(jù),因此如果可以保證ID的連續(xù)性,通過ID進行分頁是比較好的解決方案

                
                SELECT * FROM t_order WHERE id > 100000 AND id <= 100010 ORDER BY id;

          或通過記錄上次查詢結(jié)果的最后一條記錄的ID進行下一頁的查詢,例如:

                
                SELECT * FROM t_order WHERE id > 10000000 LIMIT 10;

          數(shù)據(jù)分片

                
                - 分庫 & 分表
          - 讀寫分離
          - 分片策略定制化
          - 無中心化分布式主鍵

          分布式事務(wù)

                
                - 標準化事務(wù)接口
          - XA強一致事務(wù)
          - 柔性事務(wù)

          數(shù)據(jù)庫治理

                
                - 配置動態(tài)化
          - 編排 & 治理
          - 數(shù)據(jù)脫敏
          - 可視化鏈路追蹤
          - 彈性伸縮(規(guī)劃中)
          c207fb309ac7a5eae7600353dd96ac69.webpimage.png

          ShardingSphere是一套開源的分布式數(shù)據(jù)庫中間件解決方案組成的生態(tài)圈,它由Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar這3款相互獨立的產(chǎn)品組成。

          他們均提供標準化的數(shù)據(jù)分片、分布式事務(wù) 和 數(shù)據(jù)庫治理功能,可適用于如Java同構(gòu)、異構(gòu)語言、云原生等各種多樣化的應(yīng)用場景。

          當一張表的數(shù)據(jù)達到幾千萬時,查詢一次所花的時間會變長。業(yè)界公認MySQL單表容量在 1千萬 以下是最佳狀態(tài),因為這時它的BTREE索引樹高在3~5之間。

          垂直切分又可以分為: 垂直分庫垂直分表。

          數(shù)據(jù)切分可以分為:垂直切分水平切分。

          概念 就是根據(jù)業(yè)務(wù)耦合性,將關(guān)聯(lián)度低的不同表存儲在不同的數(shù)據(jù)庫。做法與大系統(tǒng)拆分為多個小系統(tǒng)類似,按業(yè)務(wù)分類進行獨立劃分。與"微服務(wù)治理"的做法相似

          e75c252d7821f8b2d5747f8cd65a3506.webpimage.png

          一開始我們是單體服務(wù),所以只有一個數(shù)據(jù)庫,所有的表都在這個庫里。

          后來因為業(yè)務(wù)需求,單體服務(wù)變成微服務(wù)治理。所以將之前的一個商品庫,拆分成多個數(shù)據(jù)庫。每個微服務(wù)對應(yīng)一個數(shù)據(jù)庫。

          垂直分表把一個表的多個字段分別拆成多個表,一般按字段的冷熱拆分,熱字段一個表,冷字段一個表。從而提升了數(shù)據(jù)庫性能。

          dc85aac7a86bc006ac296e3669f9bd0a.webpimage.png

          一開始商品表中包含商品的所有字段,但是我們發(fā)現(xiàn):

          1.商品詳情和商品屬性字段較長。2.商品列表的時候我們是不需要顯示商品詳情和商品屬性信息,只有在點進商品的時候才會展示商品詳情信息。

          所以可以考慮把商品詳情和商品屬性單獨切分一張表,提高查詢效率。

          • 解決業(yè)務(wù)系統(tǒng)層面的耦合,業(yè)務(wù)清晰
          • 與微服務(wù)的治理類似,也能對不同業(yè)務(wù)的數(shù)據(jù)進行分級管理、維護、監(jiān)控、擴展等
          • 高并發(fā)場景下,垂直切分一定程度的提升IO、數(shù)據(jù)庫連接數(shù)、單機硬件資源的瓶頸
          • 分庫后無法Join,只能通過接口聚合方式解決,提升了開發(fā)的復(fù)雜度
          • 分庫后分布式事務(wù)處理復(fù)雜
          • 依然存在單表數(shù)據(jù)量過大的問題(需要水平切分)

          當一個應(yīng)用難以再細粒度的垂直切分或切分后數(shù)據(jù)量行數(shù)巨大,存在單庫讀寫、存儲性能瓶頸,這時候就需要進行水平切分了。

          水平切分也可以分為:水平分庫水平分表

          商品庫分成3個庫,但是隨著業(yè)務(wù)的增加一個訂單庫也出現(xiàn)QPS過高,數(shù)據(jù)庫響應(yīng)速度來不及,一般mysql單機也就1000左右的QPS,如果超過1000就要考慮分庫。

          3c932a3fcaf8ff69a6ba4a1d3e8f30b9.webpimage.png

          一般我們一張表的數(shù)據(jù)不要超過1千萬,如果表數(shù)據(jù)超過1千萬,并且還在不斷增加數(shù)據(jù),那就可以考慮分表。

          727da60602f15a63a233f3c4287aa28b.webpimage.png
          • 不存在單庫數(shù)據(jù)量過大、高并發(fā)的性能瓶頸,提升系統(tǒng)穩(wěn)定性和負載能力
          • 應(yīng)用端改造較小,不需要拆分業(yè)務(wù)模塊
          • 跨分片的事務(wù)一致性難以保證
          • 跨庫的Join關(guān)聯(lián)查詢性能較差
          • 數(shù)據(jù)多次擴展難度和維護量極大

          將一張表水平切分成多張表,這就涉及到數(shù)據(jù)分片的規(guī)則,比較常見的有:Hash取模分表、數(shù)值Range分表、一致性Hash算法分表。

          一般采用Hash取模的切分方式,例如:假設(shè)按goods_id分4張表。(goods_id%4 取整確定表)

          1e5011e6a54ea247d7398ce2689f2a98.webpimage.png
          • 數(shù)據(jù)分片相對比較均勻,不容易出現(xiàn)熱點和并發(fā)訪問的瓶頸。
          • 后期分片集群擴容時,需要遷移舊的數(shù)據(jù)很難。
          • 容易面臨跨分片查詢的復(fù)雜問題。比如上例中,如果頻繁用到的查詢條件中不帶goods_id時,將會導(dǎo)致無法定位數(shù)據(jù)庫,從而需要同時向4個庫發(fā)起查詢, 再在內(nèi)存中合并數(shù)據(jù),取最小集返回給應(yīng)用,分庫反而成為拖累。

          按照時間區(qū)間或ID區(qū)間來切分。例如:將goods_id為11000的記錄分到第一個表,10012000的分到第二個表,以此類推。

          eae42f28c58e8a87af78f5dbc1bf8942.webpimage.png
          • 單表大小可控 - 天然便于水平擴展,后期如果想對整個分片集群擴容時,只需要添加節(jié)點即可,無需對其他分片的數(shù)據(jù)進行遷移
          • 使用分片字段進行范圍查找時,連續(xù)分片可快速定位分片進行快速查詢,有效避免跨分片查詢的問題。
          • 熱點數(shù)據(jù)成為性能瓶頸。 例如按時間字段分片,有些分片存儲最近時間段內(nèi)的數(shù)據(jù),可能會被頻繁的讀寫,而有些分片存儲的歷史數(shù)據(jù),則很少被查詢

          一致性Hash算法能很好的解決因為Hash取模而產(chǎn)生的分片集群擴容時,需要遷移舊的數(shù)據(jù)的難題。

          任何事情都有兩面性,分庫分表也不例外,如果采用分庫分表,會引入新的的問題

          用分布式事務(wù)中間件解決,具體是通過最終一致性還是強一致性分布式事務(wù),看業(yè)務(wù)需求

          切分之前,我們可以通過Join來完成。而切分之后,數(shù)據(jù)可能分布在不同的節(jié)點上,此時Join帶來的問題就比較麻煩了,考慮到性能,盡量避免使用Join查詢。

          全局表,也可看做是 "數(shù)據(jù)字典表",就是系統(tǒng)中所有模塊都可能依賴的一些表,為了避免跨庫Join查詢,可以將 這類表在每個數(shù)據(jù)庫中都保存一份。這些數(shù)據(jù)通常

          很少會進行修改,所以也不擔心一致性的問題。

          利用空間換時間,為了性能而避免join查詢。例:訂單表保存userId時候,也將userName冗余保存一份,這樣查詢訂單詳情時就不需要再去查詢"買家user表"了。

          在系統(tǒng)層面,分兩次查詢。第一次查詢的結(jié)果集中找出關(guān)聯(lián)數(shù)據(jù)id,然后根據(jù)id發(fā)起第二次請求得到關(guān)聯(lián)數(shù)據(jù)。最后將獲得到的數(shù)據(jù)進行字段拼裝。

          跨節(jié)點多庫進行查詢時,會出現(xiàn)Limit分頁、Order by排序等問題。分頁需要按照指定字段進行排序,當排序字段就是分片字段時,通過分片規(guī)則就比較容易定位到指定的分片;

          當排序字段非分片字段時,就變得比較復(fù)雜了。需要先在不同的分片節(jié)點中將數(shù)據(jù)進行排序并返回,然后將不同分片返回的結(jié)果集進行匯總和再次排序,最終返回給用戶。

          如果都用主鍵自增肯定不合理,如果用UUID那么無法做到根據(jù)主鍵排序,所以我們可以考慮通過雪花ID來作為數(shù)據(jù)庫的主鍵,

          采用雙寫的方式,修改代碼,所有涉及到分庫分表的表的增、刪、改的代碼,都要對新庫進行增刪改。同時,再有一個數(shù)據(jù)抽取服務(wù),不斷地從老庫抽數(shù)據(jù),往新庫寫,

          邊寫邊按時間比較數(shù)據(jù)是不是最新的。

          每個微服務(wù)使用單獨的一個數(shù)據(jù)庫

          加群聯(lián)系作者vx:xiaoda0423

          倉庫地址:https://github.com/webVueBlog/JavaGuideInterview

          瀏覽 28
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  污网址在线 | 国产精品久久久久久亚洲色 | 四虎国产精品成人永久免费 | 大香蕉久操国产 | 深爱五月丁香花 |