本篇文章為大家展示了MongoDB從入坑到入迷的過(guò)程是怎樣的,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。
創(chuàng)新互聯(lián)長(zhǎng)期為上1000+客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為廊坊企業(yè)提供專業(yè)的做網(wǎng)站、網(wǎng)站設(shè)計(jì),廊坊網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
背景:我司是一家正處于高速發(fā)展,目前擁有數(shù)百萬(wàn)用戶,年銷售額近五十億的社交電商公司。公司技術(shù)部建立之初,為了適應(yīng)用戶量的高速增長(zhǎng),與業(yè)務(wù)的不斷變更迭代,在選用數(shù)據(jù)庫(kù)的時(shí)候,經(jīng)過(guò)調(diào)研對(duì)比我們選擇了MongoDB。
是的,你沒(méi)看錯(cuò),All in MongoDB!
1.為什么使用MongoDB
因?yàn)槲宜局饕錾缃浑娚痰臉I(yè)務(wù),所以對(duì)數(shù)據(jù)庫(kù)的性能有一定的要求,加上商品交易是公司主要盈利來(lái)源,所以對(duì)數(shù)據(jù)庫(kù)的高可用也有一定的要求。
總結(jié)一下我們對(duì)數(shù)據(jù)庫(kù)的要求:
安全,穩(wěn)定
高可用
高性能
我們?cè)诳紤]數(shù)據(jù)庫(kù)選型的時(shí)候主要考慮什么?
數(shù)據(jù)規(guī)模
支持讀寫并發(fā)量
延遲與吞吐量
從數(shù)據(jù)規(guī)模來(lái)說(shuō)訂單和商品SKU,還有會(huì)員信息這些重要的數(shù)據(jù)記錄肯定會(huì)隨著時(shí)間源源不斷的增長(zhǎng),所以我們需要的不僅僅是滿足當(dāng)下要求,更需要為半年一年后海量數(shù)據(jù)更為方便的擴(kuò)容做考量!
下面我們從MongoDB的架構(gòu),性能,和文檔模型來(lái)介紹一下我們選擇MongoDB的理由!
2.MongoDB架構(gòu)
2.1 關(guān)于高可用
數(shù)據(jù)庫(kù)作為系統(tǒng)核心,要保證99.99%的可用性,而高可用的保證來(lái)自于MongoDB冗余數(shù)據(jù)的復(fù)制集模式。MongoDB自帶多副本高可用,只需要合理的配置,就能避免單數(shù)據(jù)庫(kù)節(jié)點(diǎn)故障導(dǎo)致服務(wù)的不可用。
圖例說(shuō)明:
一個(gè)Primary主節(jié)點(diǎn),主要接受來(lái)自server的讀寫;
兩個(gè)Secondary從節(jié)點(diǎn),用于同步來(lái)自Primary的數(shù)據(jù)。
關(guān)于高可用:當(dāng)主節(jié)點(diǎn)發(fā)生故障的時(shí)候,兩個(gè)從節(jié)點(diǎn)會(huì)進(jìn)行選舉,投票產(chǎn)生一個(gè)新的主節(jié)點(diǎn),進(jìn)而保證服務(wù)的可用性。(PS:在選舉過(guò)程中數(shù)據(jù)不可寫入,但是如果Secnondary節(jié)點(diǎn)配置可讀,那么此時(shí)是可以讀取數(shù)據(jù)的。)這就是MongoDB的高可用,配置簡(jiǎn)單,不需要引入額外的中間件或者插件去輔助數(shù)據(jù)庫(kù)節(jié)點(diǎn)間的故障轉(zhuǎn)移。
2.2 關(guān)于選舉算法《分布式一致性算法---raft》
raft協(xié)議是在leader節(jié)點(diǎn)發(fā)生故障或者網(wǎng)絡(luò)分區(qū)導(dǎo)致腦裂時(shí)如何保證分布式數(shù)據(jù)一致性的一個(gè)算法,MongoDB采用了該算法來(lái)保證當(dāng)主節(jié)點(diǎn)故障或者網(wǎng)絡(luò)分區(qū)的情況下,數(shù)據(jù)的一致性。當(dāng)然MongoDB用的和raft原版算法肯定會(huì)略有不同,MongoDB會(huì)采用Secondary向Primary拉數(shù)據(jù),而不是Primary向Secondary推數(shù)據(jù)的方式來(lái)減輕Primary的壓力等等有利于數(shù)據(jù)庫(kù)操作的方式對(duì)raft進(jìn)行改進(jìn)使用。
raft算法動(dòng)畫演示
http://thesecretlivesofdata.com/raft/
2.3 關(guān)于超大規(guī)模復(fù)制集(集群)
{ "_id" : <num>, "host" : <hostname:port>, "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 0, // 設(shè)置為0 "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 0 // 設(shè)置為0 }
MongoDB最多允許50個(gè)節(jié)點(diǎn),但是最多只有7個(gè)節(jié)點(diǎn)有投票權(quán),一個(gè)節(jié)點(diǎn)可以配置7個(gè)無(wú)投票權(quán)的Non-Voting節(jié)點(diǎn),加上一個(gè)Primary節(jié)點(diǎn)。
為什么只能允許存在7個(gè)投票節(jié)點(diǎn)呢?參考2.2小節(jié)的raft算法,節(jié)點(diǎn)越多,投票時(shí)間越長(zhǎng),選舉出來(lái)的Primary節(jié)點(diǎn)時(shí)間也就越長(zhǎng),這個(gè)過(guò)程中我們是無(wú)法進(jìn)行寫操作的,因?yàn)闆](méi)有主節(jié)點(diǎn)。
那么多非投票節(jié)點(diǎn)有什么用呢?大家應(yīng)該都聽過(guò)MySQL的讀寫分離吧,利用讀寫分離來(lái)提高數(shù)據(jù)庫(kù)性能。 MongoDB這里其實(shí)也可以,Primary用來(lái)寫,Secondary用來(lái)讀,可以給BI部門一個(gè)Secondary,給財(cái)務(wù)部門一個(gè)Secondary,給運(yùn)營(yíng)部門一個(gè)Secondary······
2.4 WriteConcern
既然我們的數(shù)據(jù)庫(kù)擁有至少超過(guò)三個(gè)節(jié)點(diǎn)(1Primary+2Secondary),Secondary通過(guò)同步Primary的數(shù)據(jù)來(lái)保持一致性,那么當(dāng)我們寫操作的時(shí)候,如何保證數(shù)據(jù)安全的落盤呢?
有以下幾種情況:
1. 寫Primary成功,返回客戶端寫成功,Secondary還未同步Primary的時(shí)候,Primary掛了,數(shù)據(jù)丟失!
2. 寫Primary成功,數(shù)據(jù)同步一個(gè)Secondary成功,返回客戶端寫成功。此時(shí)Primary掛了,數(shù)據(jù)不會(huì)丟失。但是恰好Primary與同步的Secondary同時(shí)掛了,數(shù)據(jù)丟失!
3. 寫Primary成功,數(shù)據(jù)同步兩個(gè)Secondary成功,返回客戶端寫成功。此時(shí)Primary掛了,數(shù)據(jù)不會(huì)丟失。
我們對(duì)以上三種情況進(jìn)行分析:第一種情況有風(fēng)險(xiǎn)會(huì)造成數(shù)據(jù)丟失。第二種情況還是會(huì)出現(xiàn)數(shù)據(jù)丟失,但是數(shù)據(jù)丟失的概率大大降低。第三種情況是最安全的做法,但是節(jié)點(diǎn)數(shù)目多了,同步非常耗時(shí),用戶需要等待的時(shí)間過(guò)長(zhǎng),一般不考慮。
MongoDB在這里推薦折衷方案就是使用Write Concern---在數(shù)據(jù)可靠性與效率之間的權(quán)衡!
db.products.insert( { item: "envelopes", qty : 100, type: "Clasp" }, { writeConcern: { w: "majority" , wtimeout: 5000 } } // 設(shè)置writeConcern為majority,超時(shí)時(shí)間為5000毫秒 )
3.MongoDB分片
3.1 大規(guī)模數(shù)據(jù)是如何影響數(shù)據(jù)庫(kù)效率的?
數(shù)據(jù)庫(kù)的性能還與數(shù)據(jù)庫(kù)本身規(guī)模息息相關(guān)。拿關(guān)系型數(shù)據(jù)庫(kù)舉例:
查詢百萬(wàn)表和千萬(wàn)表甚至過(guò)億的表效率相差很大,查詢性能急劇惡化。
插入的時(shí)候創(chuàng)建索引可能會(huì)引起索引樹的調(diào)整與頁(yè)分裂。
3.2 面對(duì)海量數(shù)據(jù)如何提升數(shù)據(jù)讀寫效率?
為了在海量數(shù)據(jù)中提升數(shù)據(jù)庫(kù)的效率,我們采用分而治之的思想,將大表拆成小表,大庫(kù)拆成小庫(kù)。
關(guān)系型數(shù)據(jù)庫(kù)中我們常用分表分庫(kù)來(lái)解決:
例如將訂單庫(kù)分為在線庫(kù)和離線庫(kù),近三個(gè)月是在線庫(kù),遠(yuǎn)期的訂單數(shù)據(jù)放入離線庫(kù),這樣在線庫(kù)的數(shù)據(jù)就大大減少,數(shù)據(jù)庫(kù)性能就得到了提升。
又例如當(dāng)我們的用戶量過(guò)多超過(guò)千萬(wàn)行記錄,單表查詢效率下降,我們將一張用戶表拆成多張用戶表,這個(gè)就是水平拆分。
MongoDB中我們是如何做的呢?
3.3 MongoDBSharding
MongoDB的分片
通過(guò)將同一個(gè)集合(Collection1)的數(shù)據(jù)按片鍵(shard keys)分到不同的分片(shard)上面,減少同一個(gè)數(shù)據(jù)文件上的數(shù)據(jù)量,已達(dá)到拆分?jǐn)?shù)據(jù)規(guī)模的目的。
Shard 優(yōu)勢(shì):在線擴(kuò)容,動(dòng)態(tài)擴(kuò)容
Shard:用于存儲(chǔ)實(shí)際的數(shù)據(jù)塊,實(shí)際生產(chǎn)環(huán)境中一個(gè)shard server角色可由幾臺(tái)機(jī)器組個(gè)一個(gè)replica set承擔(dān),防止主機(jī)單點(diǎn)故障。
Config Server:配置服務(wù)器 mongod實(shí)例,存儲(chǔ)了整個(gè)集群的元數(shù)據(jù)與配置,其中包括 chunk信息,在MongoDB 3.4中,配置服務(wù)器必須部署為一個(gè)副本集。
Mongos:mongos充當(dāng)查詢路由器,提供客戶端應(yīng)用程序和切分集群之間的接口。
服務(wù)器插入的數(shù)據(jù)通過(guò)Mongos路由到具體地址,這也是MongoDB的便利之處,不需要自己關(guān)注路由,也不需要使用第三方提供的中間件輔助路由,可靠,放心。
分片的負(fù)載均衡
當(dāng)我們的MongoDB 副本集變成分片集群后,隨著數(shù)據(jù)量的增長(zhǎng),各個(gè)分片也會(huì)越來(lái)越大,這里就會(huì)出現(xiàn)兩種情況:
1. 冷熱數(shù)據(jù),某個(gè)分片數(shù)據(jù)量過(guò)大。
2. 數(shù)據(jù)總量大,分片集群的分片過(guò)大。
當(dāng)出現(xiàn)問(wèn)題(1)的時(shí)候,MongoDB的負(fù)載均衡器(Balancer)會(huì)自動(dòng)將大分片中的數(shù)據(jù)遷往小分片。注意這并不意味我們可以高枕無(wú)憂了,恰恰相反,我們應(yīng)該反思是不是自己片鍵選擇失誤而造成的數(shù)據(jù)不均勻!因?yàn)閷?duì)分片遷移也是消耗性能的,應(yīng)用服務(wù)器寫一次到Shard B,然后Shard B重寫到Shard C無(wú)形之中數(shù)據(jù)被寫了兩次,這是極大的浪費(fèi)!
當(dāng)出現(xiàn)問(wèn)題(2)的時(shí)候,當(dāng)然是給過(guò)大的分片集合添加新的分片以此分?jǐn)偡制旱膲毫Α?/p>
注意:MongoDB分片雖然是可在線的,但是多少都會(huì)對(duì)正常的讀寫操作性能有一定的影響,建議在非繁忙時(shí)間段進(jìn)行分片部署!
4.MongoDB文檔模型介紹
數(shù)據(jù)庫(kù)建模的挑戰(zhàn)在于平衡應(yīng)用的需要,適合該數(shù)據(jù)庫(kù)引擎發(fā)揮的結(jié)構(gòu)以及數(shù)據(jù)的檢索模式。當(dāng)我們?cè)O(shè)計(jì)數(shù)據(jù)模型的時(shí)候,需要考慮應(yīng)用使用數(shù)據(jù)的情況(查詢,更新,和數(shù)據(jù)處理)以及該數(shù)據(jù)本身的結(jié)構(gòu)。
4.1 靈活的Schema
在關(guān)系型數(shù)據(jù)庫(kù)中,必須按照確定的表結(jié)構(gòu)去插入數(shù)據(jù)。但是,由于MongoDB是文檔型數(shù)據(jù)庫(kù),在插入數(shù)據(jù)的時(shí)候默認(rèn)并不對(duì)此做要求。其表現(xiàn)在于:
同一個(gè)集合中不同文檔不一定需要有相同的字段,并且字段類型也可以不同。
在集合中改變文檔的結(jié)構(gòu),例如增加一個(gè)字段,刪除一個(gè)字段,或者改變一個(gè)字段的類型,只需要對(duì)該文檔更新即可。
4.2 舉例1:N模型設(shè)計(jì)
在電商業(yè)務(wù)中,一個(gè)用戶可能有多個(gè)收件人以及收件地址。在關(guān)系型數(shù)據(jù)庫(kù)中,我們需要建立聯(lián)系人表,地址表,并且將其關(guān)聯(lián)。但是在MongoDB中,我們只需要一個(gè)集合就能將此搞定!
數(shù)據(jù)關(guān)系如下:
// patron document { _id: "joe", name: "Joe Bookreader" } // address documents { patron_id: "joe", // reference to patron document street: "123 Fake Street", city: "Faketon", state: "MA", zip: "12345" } { patron_id: "joe", street: "1 Some Other Street", city: "Boston", state: "MA", zip: "12345" }
在MongoDB中我們可以這樣進(jìn)行設(shè)計(jì):
{ "_id": "joe", "name": "Joe Bookreader", "addresses": [ { "street": "123 Fake Street", "city": "Faketon", "state": "MA", "zip": "12345" }, { "street": "1 Some Other Street", "city": "Boston", "state": "MA", "zip": "12345" } ] }
沒(méi)錯(cuò),以上就是集合中的一個(gè)document(文檔),是不是感覺(jué)很靈活很方便!你可以在SKU集合中添加分類信息,或者商品標(biāo)簽,還可以在庫(kù)存集合中冗余SKU的基本信息,還可以在訂單集合中冗余部分下單者信息···沒(méi)錯(cuò),就是這么靈活!這也是我們選擇MongoDB的一個(gè)重要原因之一,讓開發(fā)者的心智負(fù)擔(dān)少了很多,不需要成為SQL高手,你也能在MongoDB中寫出性能優(yōu)異的查詢語(yǔ)句。
當(dāng)然冗余一時(shí)爽,重構(gòu)火葬場(chǎng)的段子也不是沒(méi)聽過(guò),因?yàn)檫^(guò)多的冗余最終會(huì)造成數(shù)據(jù)的過(guò)于臃腫,性能降低等各種問(wèn)題,這個(gè)要控制住開發(fā)者的冗余沖動(dòng),也依賴于團(tuán)隊(duì)技術(shù)Leader對(duì)此的把關(guān)。
互聯(lián)網(wǎng)業(yè)務(wù)不是一成不變的,產(chǎn)品和用戶的需求還有市場(chǎng)都一直在變!我們沒(méi)有技術(shù)實(shí)力打造一個(gè)能夠適應(yīng)靈活多變的業(yè)務(wù)的中臺(tái),但是目前我們可以選擇一個(gè)可靠,強(qiáng)大并且靈活的數(shù)據(jù)庫(kù) -- MongoDB!
上述內(nèi)容就是MongoDB從入坑到入迷的過(guò)程是怎樣的,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站欄目:MongoDB從入坑到入迷的過(guò)程是怎樣的
路徑分享:http://www.chinadenli.net/article14/ighdge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈、服務(wù)器托管、微信公眾號(hào)、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)