類似訂單表,使用者表這種未來規模上億甚至上十億百億的海量資料表,在專案初期為了快速上線,一般只是單錶設計,不需要考慮分庫分表。隨著業務的發展,單錶容量超過千萬甚至達到億級別以上,這時候就需要考慮分庫分表這個問題了,而不停機分庫分表遷移,這應該是分庫分表最基本的需求,畢竟網際網路專案不可能掛個廣告牌"今晚10:00~次日10:00系統停機維護",這得多low呀,以後跳槽面試,你跟面試官說這個遷移方案,面試官怎麼想呀?
當遷移過程中發生資料訪問時,proxy會傳送「slotsmgrttagslot」遷移命令給redis,強制將客戶端要訪問的key立刻遷移,然後再處理客戶端的請求。( slotsmgrttagslot 是codis基於redis定製的)
確定sharding column絕對是分庫分表最最最重要的環節,沒有之一。sharding column直接決定整個分庫分表方案最終是否能成功落地;乙個合適的sharding column的選取,基本上能讓與這個表相關的絕大部分流量介面都能通過這個sharding column訪問分庫分表後的單錶,而不需要跨庫跨表,最常見的sharding column就是user_id,筆記這裡選取的也是user_id;
根據自身的業務選取最合適的sharding column後,就要確定分庫分表方案了。筆者採用主動遷移與被動遷移相結合的方案:
接下來詳細介紹這兩個方案;
public void migrate()");
if ("completed".equals(status))
if ("migrating".equals(status))
// 遷移前先獲取鎖: set migratestatus:18 migrating ex 3600 nx
string result = executeredis("set migratestatus:$ migrating ex 86400 nx");
if ("ok".equals(result)) 864000 completed");
} else ", userid);}}
if (tempmaxid >= maxid)
logger.info("migration process id = {}", tempmaxid);
}catch (throwable e)
tempminid += stepsize;
}while (tempmaxid < maxid);
}
這裡有幾點需要注意:
第一步查詢出max(id)是為了儘量減少max(id)的查詢次數,假如第一次查詢max(id)為10000000,那麼直到遍歷的id到10000000以前,都不需要再次查詢max(id);
根據id>=? and id<?遍歷,而不要根據id>=? limit n或者limit m, n進行遍歷,因為limit效能一般,且會隨著遍歷越往後,效能越差。而id>=? and id<?這種遍歷方式即使會有一些踩空,也沒有任何影響,且整個效能曲線非常平順,不會有任何抖動;遷移程式畢竟是輔助程式,不能對業務程式有過多的影響;
根據id區間範圍查詢出來的list要轉換為iterator,每迭代處理完乙個userid,要remove掉,否則可能導致gc異常,甚至oom;
public void migratepassive(long userid)throws exception");
if ("completed".equals(status)) else if ("migrating".equals(status)) ");
}while ("completed".equals(status));
}else migrating ex 86400 nx");
if ("ok".equals(result)) 864000 completed");
}else
}} // 先嘗試被動遷移}
無論是crud中哪種操作,先根據快取中migratestatus:$的值進行判斷:
當所有資料遷移完成後,crud操作還是會先根據快取中migratestatus的值進行判斷,資料遷移完成後這一步已經是多餘的。可以加個總開關,當所有資料遷移完成後,將這個開關的值通過類似topic的方式傳送,所有服務接收到topic後將開關local cache化。那麼接下來服務的crud都不需要先根據快取中migratestatus:$的值進行判斷;
遷移完成後,將主動遷移程式下線,並將被動遷移程式中對migratepassive()的呼叫全部去掉,並可以整合一些第三方分庫分表中介軟體,例如sharding-jdbc,可以參考sharding-jdbc整合實戰
回顧這個方案,最大的缺點就是如果碰到sharding column(例如userid)的總記錄數比較多,且主動遷移正在進行中,被動遷移與主動遷移碰撞,那麼被動遷移可能需要等待較長時間。
不過根據db效能,一般批量插入1000條資料都是10ms級別,並且同一sharding column的記錄分庫分表後只屬於一張表,不涉及跨表。所以,只要在遷移前先通過sql統計待遷移表中沒有這類異常sharding column即可放心遷移;
如果有那種上萬條記錄的sharding column,可以把這些sharding column先快取起來,遷移程式在夜間上線,優先遷移這些快取的sharding column的資料,就可以盡可能的降低遷移程式對這些使用者的體驗。當然你也可以使用你想出來的更好的方案。
網易遊戲如何做到不停服維護?
如何做到不停服維護?不停服維護在運維上會帶來哪些改變和公升級?作為 sre 該如何應對?1月20日,網易遊戲高階運維經理richard在2019網易遊戲開發者峰會上,為大家分享了網易遊戲半年來的積累的一些經驗。我在這裡要和大家分享的是遊戲不停服維護運維實踐。遊戲維護是我工作以來一直無法迴避的乙個話題...
求職者和面試官如何做好電話面試
面試方式有很多種,其中 面試是較為特殊性的,因為雙方不是面對面,而是通過 傳聲的,所以作為求職者和面試官如何做好 面試呢?應聘者應對 面試?1 主動選擇通話時間 接到 的地點可能在任何地方,街道 商場 公共汽車站等等,這些地方聲音嘈雜,不利於溝通,這時,你可以主動要求另約時間再聯絡,如說 對不起,我...
如何當好面試官
今年面試的人比較多,加起來快一百人了。由於面試任務比較多,也有越來越多的小夥伴加入了面試官的行列。總結一些面試相關的方 希望新晉面試官有些幫助,最終能高效面試。面試官的目標是為組織找到合適的人,一切行為都是圍繞這個主體來運作的。我們現在的面試還是類似於考試,這是一種能夠在短時間內高效選擇到合格面試者...