激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫(kù)技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫(kù) - Mysql - 從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

2020-11-09 23:15冰河技術(shù)冰河 Mysql

很多小伙伴留言說(shuō)讓我寫(xiě)一些工作過(guò)程中的真實(shí)案例,寫(xiě)些啥呢?想來(lái)想去,寫(xiě)一篇我在以前公司從零開(kāi)始到用戶超千萬(wàn)的MYSQL數(shù)據(jù)庫(kù)架構(gòu)升級(jí)演變的過(guò)程吧。

作者個(gè)人研發(fā)的在高并發(fā)場(chǎng)景下,提供的簡(jiǎn)單、穩(wěn)定、可擴(kuò)展的延遲消息隊(duì)列框架,具有精準(zhǔn)的定時(shí)任務(wù)和延遲隊(duì)列處理功能。自開(kāi)源半年多以來(lái),已成功為十幾家中小型企業(yè)提供了精準(zhǔn)定時(shí)調(diào)度方案,經(jīng)受住了生產(chǎn)環(huán)境的考驗(yàn)。為使更多童鞋受益,現(xiàn)給出開(kāi)源框架地址:https://github.com/sunshinelyz/mykit-delay

寫(xiě)在前面

很多小伙伴留言說(shuō)讓我寫(xiě)一些工作過(guò)程中的真實(shí)案例,寫(xiě)些啥呢?想來(lái)想去,寫(xiě)一篇我在以前公司從零開(kāi)始到用戶超千萬(wàn)的數(shù)據(jù)庫(kù)架構(gòu)升級(jí)演變的過(guò)程吧。

本文記錄了我之前初到一家創(chuàng)業(yè)公司,從零開(kāi)始到用戶超千萬(wàn),系統(tǒng)壓力暴增的情況下是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的,以及數(shù)據(jù)庫(kù)架構(gòu)升級(jí)的演變過(guò)程。升級(jí)的過(guò)程極具技術(shù)挑戰(zhàn)性,也從中收獲不少。希望能夠?yàn)樾』锇閭儙?lái)實(shí)質(zhì)性的幫助。

業(yè)務(wù)背景

我之前呆過(guò)一家創(chuàng)業(yè)工作,是做商城業(yè)務(wù)的,商城這種業(yè)務(wù),表面上看起來(lái)涉及的業(yè)務(wù)簡(jiǎn)單,包括:用戶、商品、庫(kù)存、訂單、購(gòu)物車、支付、物流等業(yè)務(wù)。但是,細(xì)分下來(lái),還是比較復(fù)雜的。這其中往往會(huì)牽扯到很多提升用戶體驗(yàn)的潛在需求。例如:為用戶推薦商品,這就涉及到用戶的行為分析和大數(shù)據(jù)的精準(zhǔn)推薦。如果說(shuō)具體的技術(shù)的話,那肯定就包含了:用戶行為日志埋點(diǎn)、采集、上報(bào),大數(shù)據(jù)實(shí)時(shí)統(tǒng)計(jì)分析,用戶畫(huà)像,商品推薦等大數(shù)據(jù)技術(shù)。

公司的業(yè)務(wù)增長(zhǎng)迅速,僅僅2年半不到的時(shí)間用戶就從零積累到千萬(wàn)級(jí)別,每天的訪問(wèn)量幾億次,高峰QPS高達(dá)上萬(wàn)次每秒,雙十一期間的訪問(wèn)量和QPS是平時(shí)的幾倍。數(shù)據(jù)的寫(xiě)壓力來(lái)源于用戶下單,支付等操作,尤其是趕上雙十一大促期間,系統(tǒng)的寫(xiě)壓力會(huì)成倍增長(zhǎng)。然而,讀業(yè)務(wù)的壓力會(huì)遠(yuǎn)遠(yuǎn)大于寫(xiě)壓力,據(jù)不完全統(tǒng)計(jì),讀業(yè)務(wù)的請(qǐng)求量是寫(xiě)業(yè)務(wù)的請(qǐng)求量的50倍左右。

接下來(lái),我們就一起來(lái)看看數(shù)據(jù)庫(kù)是如何升級(jí)的。

最初的技術(shù)選型

作為創(chuàng)業(yè)公司,最重要的一點(diǎn)是敏捷,快速實(shí)現(xiàn)產(chǎn)品,對(duì)外提供服務(wù),于是我們選擇了公有云服務(wù),保證快速實(shí)施和可擴(kuò)展性,節(jié)省了自建機(jī)房等時(shí)間。整體后臺(tái)采用的是Java語(yǔ)言進(jìn)行開(kāi)發(fā),數(shù)據(jù)庫(kù)使用的MySQL。整體如下圖所示。

從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

讀寫(xiě)分離

隨著業(yè)務(wù)的發(fā)展,訪問(wèn)量的極速增長(zhǎng),上述的方案很快不能滿足性能需求。每次請(qǐng)求的響應(yīng)時(shí)間越來(lái)越長(zhǎng),比如用戶在H5頁(yè)面上不斷刷新商品,響應(yīng)時(shí)間從最初的500毫秒增加到了2秒以上。業(yè)務(wù)高峰期,系統(tǒng)甚至出現(xiàn)過(guò)宕機(jī)。在這生死存亡的關(guān)鍵時(shí)刻,通過(guò)監(jiān)控,我們發(fā)現(xiàn)高峰期MySQL CPU使用率已接近80%,磁盤IO使用率接近90%,slow query(慢查詢)從每天1百條上升到1萬(wàn)條,而且一天比一天嚴(yán)重。數(shù)據(jù)庫(kù)儼然已成為瓶頸,我們必須得快速做架構(gòu)升級(jí)。

當(dāng)Web應(yīng)用服務(wù)出現(xiàn)性能瓶頸的時(shí)候,由于服務(wù)本身無(wú)狀態(tài),我們可以通過(guò)加機(jī)器的水平擴(kuò)展方式來(lái)解決。而數(shù)據(jù)庫(kù)顯然無(wú)法通過(guò)簡(jiǎn)單的添加機(jī)器來(lái)實(shí)現(xiàn)擴(kuò)展,因此我們采取了MySQL主從同步和應(yīng)用服務(wù)端讀寫(xiě)分離的方案。

MySQL支持主從同步,實(shí)時(shí)將主庫(kù)的數(shù)據(jù)增量復(fù)制到從庫(kù),而且一個(gè)主庫(kù)可以連接多個(gè)從庫(kù)同步。利用此特性,我們?cè)趹?yīng)用服務(wù)端對(duì)每次請(qǐng)求做讀寫(xiě)判斷,若是寫(xiě)請(qǐng)求,則把這次請(qǐng)求內(nèi)的所有DB操作發(fā)向主庫(kù);若是讀請(qǐng)求,則把這次請(qǐng)求內(nèi)的所有DB操作發(fā)向從庫(kù),如下圖所示。

從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

實(shí)現(xiàn)讀寫(xiě)分離后,數(shù)據(jù)庫(kù)的壓力減少了許多,CPU使用率和IO使用率都降到了5%以內(nèi),Slow Query(慢查詢)也趨近于0。主從同步、讀寫(xiě)分離給我們主要帶來(lái)如下兩個(gè)好處:

  • 減輕了主庫(kù)(寫(xiě))壓力:商城業(yè)務(wù)主要來(lái)源于讀操作,做讀寫(xiě)分離后,讀壓力轉(zhuǎn)移到了從庫(kù),主庫(kù)的壓力減小了數(shù)十倍。
  • 從庫(kù)(讀)可水平擴(kuò)展(加從庫(kù)機(jī)器):因系統(tǒng)壓力主要是讀請(qǐng)求,而從庫(kù)又可水平擴(kuò)展,當(dāng)從庫(kù)壓力太時(shí),可直接添加從庫(kù)機(jī)器,緩解讀請(qǐng)求壓力。

當(dāng)然,沒(méi)有一個(gè)方案是萬(wàn)能的。讀寫(xiě)分離,暫時(shí)解決了MySQL壓力問(wèn)題,同時(shí)也帶來(lái)了新的挑戰(zhàn)。業(yè)務(wù)高峰期,用戶提交完訂單,在我的訂單列表中卻看不到自己提交的訂單信息(典型的read after write問(wèn)題);系統(tǒng)內(nèi)部偶爾也會(huì)出現(xiàn)一些查詢不到數(shù)據(jù)的異常。通過(guò)監(jiān)控,我們發(fā)現(xiàn),業(yè)務(wù)高峰期MySQL可能會(huì)出現(xiàn)主從復(fù)制延遲,極端情況,主從延遲高達(dá)數(shù)秒。這極大的影響了用戶體驗(yàn)。

那如何監(jiān)控主從同步狀態(tài)?在從庫(kù)機(jī)器上,執(zhí)行show slave status,查看Seconds_Behind_Master值,代表主從同步從庫(kù)落后主庫(kù)的時(shí)間,單位為秒,若主從同步無(wú)延遲,這個(gè)值為0。MySQL主從延遲一個(gè)重要的原因之一是主從復(fù)制是單線程串行執(zhí)行(高版本MySQL支持并行復(fù)制)。

那如何避免或解決主從延遲?我們做了如下一些優(yōu)化:

  • 優(yōu)化MySQL參數(shù),比如增大innodb_buffer_pool_size,讓更多操作在MySQL內(nèi)存中完成,減少磁盤操作。
  • 使用高性能CPU主機(jī)。
  • 數(shù)據(jù)庫(kù)使用物理主機(jī),避免使用虛擬云主機(jī),提升IO性能。
  • 使用SSD磁盤,提升IO性能。SSD的隨機(jī)IO性能約是SATA硬盤的10倍甚至更高。
  • 業(yè)務(wù)代碼優(yōu)化,將實(shí)時(shí)性要求高的某些操作,強(qiáng)制使用主庫(kù)做讀操作。
  • 升級(jí)高版本MySQL,支持并行主從復(fù)制。

垂直分庫(kù)

讀寫(xiě)分離很好的解決了讀壓力問(wèn)題,每次讀壓力增加,可以通過(guò)加從庫(kù)的方式水平擴(kuò)展。但是寫(xiě)操作的壓力隨著業(yè)務(wù)爆發(fā)式的增長(zhǎng)沒(méi)有得到有效的緩解,比如用戶提交訂單越來(lái)越慢。通過(guò)監(jiān)控MySQL數(shù)據(jù)庫(kù),我們發(fā)現(xiàn),數(shù)據(jù)庫(kù)寫(xiě)操作越來(lái)越慢,一次普通的insert操作,甚至可能會(huì)執(zhí)行1秒以上。

另一方面,業(yè)務(wù)越來(lái)越復(fù)雜,多個(gè)應(yīng)用系統(tǒng)使用同一個(gè)數(shù)據(jù)庫(kù),其中一個(gè)很小的非核心功能出現(xiàn)延遲,常常影響主庫(kù)上的其它核心業(yè)務(wù)功能。這時(shí),主庫(kù)成為了性能瓶頸,我們意識(shí)到,必須得再一次做架構(gòu)升級(jí),將主庫(kù)做拆分,一方面以提升性能,另一方面減少系統(tǒng)間的相互影響,以提升系統(tǒng)穩(wěn)定性。這一次,我們將系統(tǒng)按業(yè)務(wù)進(jìn)行了垂直拆分。如下圖所示,將最初龐大的數(shù)據(jù)庫(kù)按業(yè)務(wù)拆分成不同的業(yè)務(wù)數(shù)據(jù)庫(kù),每個(gè)系統(tǒng)僅訪問(wèn)對(duì)應(yīng)業(yè)務(wù)的數(shù)據(jù)庫(kù),盡量避免或減少跨庫(kù)訪問(wèn)。

從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

垂直分庫(kù)過(guò)程,我們也遇到不少挑戰(zhàn),最大的挑戰(zhàn)是:不能跨庫(kù)join,同時(shí)需要對(duì)現(xiàn)有代碼重構(gòu)。單庫(kù)時(shí),可以簡(jiǎn)單的使用join關(guān)聯(lián)表查詢;拆庫(kù)后,拆分后的數(shù)據(jù)庫(kù)在不同的實(shí)例上,就不能跨庫(kù)使用join了。

例如,通過(guò)商家名查詢某個(gè)商家的所有訂單,在垂直分庫(kù)前,可以join商家和訂單表做查詢,也可以直接使用子查詢,如下如示:

select * from tb_order where supplier_id in (select id from supplier where name=’商家名稱’); 

分庫(kù)后,則要重構(gòu)代碼,先通過(guò)商家名查詢商家id,再通過(guò)商家id查詢訂單表,如下所示:

select id from supplier where name=’商家名稱’ 

select * from tb_order where supplier_id in (supplier_ids ) 

垂直分庫(kù)過(guò)程中的經(jīng)驗(yàn)教訓(xùn),使我們制定了SQL最佳實(shí)踐,其中一條便是程序中禁用或少用join,而應(yīng)該在程序中組裝數(shù)據(jù),讓SQL更簡(jiǎn)單。一方面為以后進(jìn)一步垂直拆分業(yè)務(wù)做準(zhǔn)備,另一方面也避免了MySQL中join的性能低下的問(wèn)題。

經(jīng)過(guò)近十天加班加點(diǎn)的底層架構(gòu)調(diào)整,以及業(yè)務(wù)代碼重構(gòu),終于完成了數(shù)據(jù)庫(kù)的垂直拆分。拆分之后,每個(gè)應(yīng)用程序只訪問(wèn)對(duì)應(yīng)的數(shù)據(jù)庫(kù),一方面將單點(diǎn)數(shù)據(jù)庫(kù)拆分成了多個(gè),分?jǐn)偭酥鲙?kù)寫(xiě)壓力;另一方面,拆分后的數(shù)據(jù)庫(kù)各自獨(dú)立,實(shí)現(xiàn)了業(yè)務(wù)隔離,不再互相影響。

水平分庫(kù)

讀寫(xiě)分離,通過(guò)從庫(kù)水平擴(kuò)展,解決了讀壓力;垂直分庫(kù)通過(guò)按業(yè)務(wù)拆分主庫(kù),緩存了寫(xiě)壓力,但系統(tǒng)依然存在以下隱患:

  • 單表數(shù)據(jù)量越來(lái)越大。如訂單表,單表記錄數(shù)很快就過(guò)億,超出MySQL的極限,影響讀寫(xiě)性能。
  • 核心業(yè)務(wù)庫(kù)的寫(xiě)壓力越來(lái)越大,已不能再進(jìn)一次垂直拆分,此時(shí)的系統(tǒng)架構(gòu)中,MySQL 主庫(kù)不具備水平擴(kuò)展的能力。

此時(shí),我們需要對(duì)MySQL進(jìn)一步進(jìn)行水平拆分。

從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

水平分庫(kù)面臨的第一個(gè)問(wèn)題是,按什么邏輯進(jìn)行拆分。一種方案是按城市拆分,一個(gè)城市的所有數(shù)據(jù)在一個(gè)數(shù)據(jù)庫(kù)中;另一種方案是按訂單ID平均拆分?jǐn)?shù)據(jù)。按城市拆分的優(yōu)點(diǎn)是數(shù)據(jù)聚合度比較高,做聚合查詢比較簡(jiǎn)單,實(shí)現(xiàn)也相對(duì)簡(jiǎn)單,缺點(diǎn)是數(shù)據(jù)分布不均勻,某些城市的數(shù)據(jù)量極大,產(chǎn)生熱點(diǎn),而這些熱點(diǎn)以后可能還要被迫再次拆分。按訂單ID拆分則正相反,優(yōu)點(diǎn)是數(shù)據(jù)分布均勻,不會(huì)出現(xiàn)一個(gè)數(shù)據(jù)庫(kù)數(shù)據(jù)極大或極小的情況,缺點(diǎn)是數(shù)據(jù)太分散,不利于做聚合查詢。比如,按訂單ID拆分后,一個(gè)商家的訂單可能分布在不同的數(shù)據(jù)庫(kù)中,查詢一個(gè)商家的所有訂單,可能需要查詢多個(gè)數(shù)據(jù)庫(kù)。針對(duì)這種情況,一種解決方案是將需要聚合查詢的數(shù)據(jù)做冗余表,冗余的表不做拆分,同時(shí)在業(yè)務(wù)開(kāi)發(fā)過(guò)程中,減少聚合查詢。

經(jīng)過(guò)反復(fù)思考,我們最后決定按訂單ID做水平分庫(kù)。從架構(gòu)上,將系統(tǒng)分為三層:

  • 應(yīng)用層:即各類業(yè)務(wù)應(yīng)用系統(tǒng)
  • 數(shù)據(jù)訪問(wèn)層:統(tǒng)一的數(shù)據(jù)訪問(wèn)接口,對(duì)上層應(yīng)用層屏蔽讀寫(xiě)分庫(kù)、分表、緩存等技術(shù)細(xì)節(jié)。
  • 數(shù)據(jù)層:對(duì)DB數(shù)據(jù)進(jìn)行分片,并可動(dòng)態(tài)的添加shard分片。

水平分庫(kù)的技術(shù)關(guān)鍵點(diǎn)在于數(shù)據(jù)訪問(wèn)層的設(shè)計(jì),數(shù)據(jù)訪問(wèn)層主要包含三部分:

  • 分布式緩存
  • 數(shù)據(jù)庫(kù)中間件
  • 數(shù)據(jù)異構(gòu)中間件

而數(shù)據(jù)庫(kù)中間件需要包含如下重要的功能:

  • ID生成器:生成每張表的主鍵
  • 數(shù)據(jù)源路由:將每次DB操作路由到不同的分片數(shù)據(jù)源上

ID生成器

ID生成器是整個(gè)水平分庫(kù)的核心,它決定了如何拆分?jǐn)?shù)據(jù),以及查詢存儲(chǔ)-檢索數(shù)據(jù)。ID需要跨庫(kù)全局唯一,否則會(huì)引發(fā)業(yè)務(wù)層的沖突。此外,ID必須是數(shù)字且升序,這主要是考慮到升序的ID能保證MySQL的性能(若是UUID等隨機(jī)字符串,在高并發(fā)和大數(shù)據(jù)量情況下,性能極差)。同時(shí),ID生成器必須非常穩(wěn)定,因?yàn)槿魏喂收隙紩?huì)影響所有的數(shù)據(jù)庫(kù)操作。

我們系統(tǒng)中ID生成器的設(shè)計(jì)如下所示。

從零到千萬(wàn)用戶,我是如何一步步優(yōu)化MySQL數(shù)據(jù)庫(kù)的?

  • 整個(gè)ID的二進(jìn)制長(zhǎng)度為64位
  • 前36位使用時(shí)間戳,以保證ID是升序增加
  • 中間13位是分庫(kù)標(biāo)識(shí),用來(lái)標(biāo)識(shí)當(dāng)前這個(gè)ID對(duì)應(yīng)的記錄在哪個(gè)數(shù)據(jù)庫(kù)中
  • 后15位為自增序列,以保證在同一秒內(nèi)并發(fā)時(shí),ID不會(huì)重復(fù)。每個(gè)分片庫(kù)都有一個(gè)自增序列表,生成自增序列時(shí),從自增序列表中獲取當(dāng)前自增序列值,并加1,做為當(dāng)前ID的后15位
  • 下一秒時(shí),后15位的自增序列再次從1開(kāi)始。

水平分庫(kù)是一個(gè)極具挑戰(zhàn)的項(xiàng)目,我們整個(gè)團(tuán)隊(duì)也在不斷的迎接挑戰(zhàn)中快速成長(zhǎng)。

為了適應(yīng)公司業(yè)務(wù)的不斷發(fā)展,除了在MySQL數(shù)據(jù)庫(kù)上進(jìn)行相應(yīng)的架構(gòu)升級(jí)外,我們還搭建了一套完整的大數(shù)據(jù)實(shí)時(shí)分析統(tǒng)計(jì)平臺(tái),在系統(tǒng)中對(duì)用戶的行為進(jìn)行實(shí)時(shí)分析。

關(guān)于如何搭建大數(shù)據(jù)實(shí)時(shí)分析統(tǒng)計(jì)平臺(tái),對(duì)用戶的行為進(jìn)行實(shí)時(shí)分析,我們后面再詳細(xì)介紹。

原文地址:https://mp.weixin.qq.com/s/PEh6P99X2sTm0DK4GNgnSA

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久久久久久一区二区 | 正在播放91精 | 欧美性生活视频免费 | 国产盼盼私拍福利视频99 | 国产噜噜噜 | 中文字幕欧美在线 | 看黄在线 | 免费久久精品 | 欧美一级黄色免费 | 精品亚洲午夜久久久久91 | 超级av在线| 成人 精品 | 小雪奶水翁胀公吸小说最新章节 | 91看片在线观看视频 | 亚洲网站在线播放 | 麻豆一区二区99久久久久 | 娇妻被各种姿势c到高潮小说 | 中文字幕在线看第二 | 精品国产一区二区三区久久久狼牙 | 国产亚洲自拍一区 | 激情视频免费看 | 一级少妇女片 | 毛片一级视频 | 国产午夜免费视频 | 欧美一级淫片免费播放口 | 伊人亚洲精品 | 久久亚色| 欧美黄色免费视频 | 色诱亚洲精品久久久久久 | 欧美人的天堂一区二区三区 | 成人激情视频网 | 小情侣嗯啊哦视频www | 欧美黄色大片免费观看 | 色淫影院 | 精品一区二区电影 | 日韩黄色av网站 | 亚洲小视频在线观看,com | 国产精品视频海角社区88 | 欧美精品123区 | 国产精品刺激对白麻豆99 | 成人爱爱电影 |