自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么我們選擇了MongoDB?

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù) MongoDB
我司是一家正處于高速發(fā)展,目前擁有數(shù)百萬用戶,年銷售額近五十億的社交電商公司。

 我司是一家正處于高速發(fā)展,目前擁有數(shù)百萬用戶,年銷售額近五十億的社交電商公司。

[[329559]]
圖片來自 Pexels

 

公司技術(shù)部建立之初,為了適應(yīng)用戶量的高速增長(zhǎng),與業(yè)務(wù)的不斷變更迭代,在選用數(shù)據(jù)庫(kù)的時(shí)候,經(jīng)過調(diào)研對(duì)比我們選擇了 MongoDB。

是的,你沒看錯(cuò),All in MongoDB!

本文將圍繞如下幾個(gè)部分進(jìn)行分享:

  • 為什么使用 MongoDB(選擇數(shù)據(jù)的時(shí)候我們是怎么考慮的?)
  • MongoDB 架構(gòu)(99.99% 高可用,晚上安心睡大覺!)
  • MongoDB 分片(海量數(shù)據(jù)應(yīng)對(duì)之道!)
  • MongoDB 文檔模型介紹(靈活!靈活!靈活!)

為什么使用 MongoDB

因?yàn)槲宜局饕錾缃浑娚痰臉I(yè)務(wù),所以對(duì)數(shù)據(jù)庫(kù)的性能有一定的要求,加上商品交易是公司主要盈利來源,所以對(duì)數(shù)據(jù)庫(kù)的高可用也有一定的要求。

總結(jié)一下我們對(duì)數(shù)據(jù)庫(kù)的要求:

  • 安全,穩(wěn)定
  • 高可用
  • 高性能

我們?cè)诳紤]數(shù)據(jù)庫(kù)選型的時(shí)候主要考慮什么?

  • 數(shù)據(jù)規(guī)模
  • 支持讀寫并發(fā)量
  • 延遲與吞吐量

從數(shù)據(jù)規(guī)模來說訂單和商品 SKU,還有會(huì)員信息這些重要的數(shù)據(jù)記錄肯定會(huì)隨著時(shí)間源源不斷的增長(zhǎng)。

所以我們需要的不僅僅是滿足當(dāng)下要求,更需要為半年一年后海量數(shù)據(jù)更為方便的擴(kuò)容做考量!

下面我們從 MongoDB 的架構(gòu),性能,和文檔模型來介紹一下我們選擇 MongoDB 的理由!

MongoDB 架構(gòu)

①關(guān)于高可用

數(shù)據(jù)庫(kù)作為系統(tǒng)核心,要保證 99.99% 的可用性,而高可用的保證來自于 MongoDB 冗余數(shù)據(jù)的復(fù)制集模式。

MongoDB 自帶多副本高可用,只需要合理的配置,就能避免單數(shù)據(jù)庫(kù)節(jié)點(diǎn)故障導(dǎo)致服務(wù)的不可用。

圖例說明:

 

  • 一個(gè) Primary 主節(jié)點(diǎn),主要接受來自 server 的讀寫。
  • 兩個(gè) Secondary 從節(jié)點(diǎn),用于同步來自 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:在選舉過程中數(shù)據(jù)不可寫入,但是如果 Secnondary 節(jié)點(diǎn)配置可讀,那么此時(shí)是可以讀取數(shù)據(jù)的。

這就是 MongoDB 的高可用,配置簡(jiǎn)單,不需要引入額外的中間件或者插件去輔助數(shù)據(jù)庫(kù)節(jié)點(diǎn)間的故障轉(zhuǎn)移。

②關(guān)于選舉算法《分布式一致性算法---raft》

raft 協(xié)議是在 leader 節(jié)點(diǎn)發(fā)生故障或者網(wǎng)絡(luò)分區(qū)導(dǎo)致腦裂時(shí)如何保證分布式數(shù)據(jù)一致性的一個(gè)算法,MongoDB 采用了該算法來保證當(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ù)的方式來減輕 Primary 的壓力等等有利于數(shù)據(jù)庫(kù)操作的方式對(duì) raft 進(jìn)行改進(jìn)使用。

raft 算法動(dòng)畫演示:

  1. http://thesecretlivesofdata.com/raft/ 

③關(guān)于超大規(guī)模復(fù)制集(集群)

Non-Voting Members

 

上圖是一個(gè)擁有 7 個(gè)可投票從節(jié)點(diǎn),一個(gè)主節(jié)點(diǎn),兩個(gè)不可投票從節(jié)點(diǎn)。

  1.    "_id" : <num>, 
  2.    "host" : <hostname:port>, 
  3.    "arbiterOnly" : false
  4.    "buildIndexes" : true
  5.    "hidden" : false
  6.    "priority" : 0,  // 設(shè)置為0 
  7.    "tags" : { 
  8.  
  9.  
  10.    }, 
  11.    "slaveDelay" : NumberLong(0), 
  12.    "votes" : 0  // 設(shè)置為0 

MongoDB 最多允許 50 個(gè)節(jié)點(diǎn),但是最多只有 7 個(gè)節(jié)點(diǎn)有投票權(quán),一個(gè)節(jié)點(diǎn)可以配置 7 個(gè)無投票權(quán)的 Non-Voting 節(jié)點(diǎn),加上一個(gè) Primary 節(jié)點(diǎn)。

為什么只能允許存在 7 個(gè)投票節(jié)點(diǎn)呢?參考上節(jié)的 raft 算法,節(jié)點(diǎn)越多,投票時(shí)間越長(zhǎng),選舉出來的 Primary 節(jié)點(diǎn)時(shí)間也就越長(zhǎng),這個(gè)過程中我們是無法進(jìn)行寫操作的,因?yàn)闆]有主節(jié)點(diǎn)。

那么多非投票節(jié)點(diǎn)有什么用呢?大家應(yīng)該都聽過 MySQL 的讀寫分離吧,利用讀寫分離來提高數(shù)據(jù)庫(kù)性能。

MongoDB 這里其實(shí)也可以,Primary 用來寫,Secondary 用來讀,可以給 BI 部門一個(gè) Secondary,給財(cái)務(wù)部門一個(gè) Secondary,給運(yùn)營(yíng)部門一個(gè) Secondary······

④WriteConcern

既然我們的數(shù)據(jù)庫(kù)擁有至少超過三個(gè)節(jié)點(diǎn)(1Primary+2Secondary),Secondary 通過同步 Primary 的數(shù)據(jù)來保持一致性,那么當(dāng)我們寫操作的時(shí)候,如何保證數(shù)據(jù)安全的落盤呢?

 

有以下幾種情況:

  • 寫 Primary 成功,返回客戶端寫成功,Secondary 還未同步 Primary 的時(shí)候,Primary 掛了,數(shù)據(jù)丟失!
  • 寫 Primary 成功,數(shù)據(jù)同步一個(gè) Secondary 成功,返回客戶端寫成功。此時(shí) Primary 掛了,數(shù)據(jù)不會(huì)丟失。但是恰好 Primary 與同步的 Secondary 同時(shí)掛了,數(shù)據(jù)丟失!
  • 寫 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í)間過長(zhǎng),一般不考慮。

MongoDB 在這里推薦折衷方案就是使用 Write Concern---在數(shù)據(jù)可靠性與效率之間的權(quán)衡!

  1. db.products.insert
  2.    { item: "envelopes", qty : 100, type: "Clasp" }, 
  3.    { writeConcern: { w: "majority" , wtimeout: 5000 } }  // 設(shè)置writeConcern為majority,超時(shí)時(shí)間為5000毫秒 

MongoDB 分片

①大規(guī)模數(shù)據(jù)是如何影響數(shù)據(jù)庫(kù)效率的?

  • 數(shù)據(jù)庫(kù)的性能還與數(shù)據(jù)庫(kù)本身規(guī)模息息相關(guān)。拿關(guān)系型數(shù)據(jù)庫(kù)舉例:
  • 查詢百萬表和千萬表甚至過億的表效率相差很大,查詢性能急劇惡化。

插入的時(shí)候創(chuàng)建索引可能會(huì)引起索引樹的調(diào)整與頁分裂。

②面對(duì)海量數(shù)據(jù)如何提升數(shù)據(jù)讀寫效率?

為了在海量數(shù)據(jù)中提升數(shù)據(jù)庫(kù)的效率,我們采用分而治之的思想,將大表拆成小表,大庫(kù)拆成小庫(kù)。

關(guān)系型數(shù)據(jù)庫(kù)中我們常用分表分庫(kù)來解決:

  • 例如將訂單庫(kù)分為在線庫(kù)和離線庫(kù),近三個(gè)月是在線庫(kù),遠(yuǎn)期的訂單數(shù)據(jù)放入離線庫(kù),這樣在線庫(kù)的數(shù)據(jù)就大大減少,數(shù)據(jù)庫(kù)性能就得到了提升。
  • 又例如當(dāng)我們的用戶量過多超過千萬行記錄,單表查詢效率下降,我們將一張用戶表拆成多張用戶表,這個(gè)就是水平拆分。

MongoDB 中我們是如何做的呢?

③MongoDBSharding

 

MongoDB 的分片

通過將同一個(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ù)器 mongodb 實(shí)例,存儲(chǔ)了整個(gè)集群的元數(shù)據(jù)與配置,其中包括 chunk 信息,在 MongoDB 3.4 中,配置服務(wù)器必須部署為一個(gè)副本集。

Mongos:mongos 充當(dāng)查詢路由器,提供客戶端應(yīng)用程序和切分集群之間的接口。

服務(wù)器插入的數(shù)據(jù)通過 Mongos 路由到具體地址,這也是 MongoDB 的便利之處,不需要自己關(guān)注路由,也不需要使用第三方提供的中間件輔助路由,可靠,放心。

分片的負(fù)載均衡

 

當(dāng)我們的 MongoDB 副本集變成分片集群后,隨著數(shù)據(jù)量的增長(zhǎng),各個(gè)分片也會(huì)越來越大。

這里就會(huì)出現(xiàn)兩種情況:

  • 冷熱數(shù)據(jù),某個(gè)分片數(shù)據(jù)量過大。
  • 數(shù)據(jù)總量大,分片集群的分片過大。

當(dāng)出現(xiàn)問題(1)的時(shí)候,MongoDB 的負(fù)載均衡器(Balancer)會(huì)自動(dòng)將大分片中的數(shù)據(jù)遷往小分片。

注意這并不意味我們可以高枕無憂了,恰恰相反,我們應(yīng)該反思是不是自己片鍵選擇失誤而造成的數(shù)據(jù)不均勻!

因?yàn)閷?duì)分片遷移也是消耗性能的,應(yīng)用服務(wù)器寫一次到 Shard B,然后 Shard B 重寫到 Shard C 無形之中數(shù)據(jù)被寫了兩次,這是極大的浪費(fèi)!

當(dāng)出現(xiàn)問題(2)的時(shí)候,當(dāng)然是給過大的分片集合添加新的分片以此分?jǐn)偡制旱膲毫Α?/p>

注意:MongoDB 分片雖然是可在線的,但是多少都會(huì)對(duì)正常的讀寫操作性能有一定的影響,建議在非繁忙時(shí)間段進(jìn)行分片部署!

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)。

①靈活的 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ì)該文檔更新即可。

②舉例 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)系如下:

  1. // patron document 
  2.    _id: "joe"
  3.    name"Joe Bookreader" 
  4.  
  5.  
  6. // address documents 
  7.    patron_id: "joe", // reference to patron document 
  8.    street: "123 Fake Street"
  9.    city: "Faketon"
  10.    state: "MA"
  11.    zip: "12345" 
  12.  
  13.  
  14.    patron_id: "joe"
  15.    street: "1 Some Other Street"
  16.    city: "Boston"
  17.    state: "MA"
  18.    zip: "12345" 

在 MongoDB 中我們可以這樣進(jìn)行設(shè)計(jì):

  1.    "_id""joe"
  2.    "name""Joe Bookreader"
  3.    "addresses": [ 
  4.                 { 
  5.                   "street""123 Fake Street"
  6.                   "city""Faketon"
  7.                   "state""MA"
  8.                   "zip""12345" 
  9.                 }, 
  10.                 { 
  11.                   "street""1 Some Other Street"
  12.                   "city""Boston"
  13.                   "state""MA"
  14.                   "zip""12345" 
  15.                 } 
  16.               ] 
  17.  } 

沒錯(cuò),以上就是集合中的一個(gè) document(文檔),是不是感覺很靈活很方便!

你可以在 SKU 集合中添加分類信息,或者商品標(biāo)簽,還可以在庫(kù)存集合中冗余 SKU 的基本信息,還可以在訂單集合中冗余部分下單者信息···沒錯(cuò),就是這么靈活!

這也是我們選擇 MongoDB 的一個(gè)重要原因之一,讓開發(fā)者的心智負(fù)擔(dān)少了很多,不需要成為 SQL 高手,你也能在 MongoDB 中寫出性能優(yōu)異的查詢語句。

當(dāng)然,“冗余一時(shí)爽,重構(gòu)火葬場(chǎng)”的段子也不是沒聽過,因?yàn)檫^多的冗余最終會(huì)造成數(shù)據(jù)的過于臃腫,性能降低等各種問題,這個(gè)要控制住開發(fā)者的冗余沖動(dòng),也依賴于團(tuán)隊(duì)技術(shù) Leader 對(duì)此的把關(guān)。

總結(jié)

互聯(lián)網(wǎng)業(yè)務(wù)不是一成不變的,產(chǎn)品和用戶的需求還有市場(chǎng)都一直在變!我們沒有技術(shù)實(shí)力打造一個(gè)能夠適應(yīng)靈活多變的業(yè)務(wù)的中臺(tái),但是目前我們可以選擇一個(gè)可靠,強(qiáng)大并且靈活的數(shù)據(jù)庫(kù) MongoDB!

作者:唐銀鵬

簡(jiǎn)介:開源愛好者、Gopher。從事電商、IM 系統(tǒng)深度研發(fā),MongoDB 愛好者,公眾號(hào)《從菜鳥到大佬》作者。

編輯:陶家龍

出處:轉(zhuǎn)載自微信公眾號(hào)Mongoing 中文社區(qū)(ID:mongoing-mongoing),本文是唐銀鵬在“青芒話生長(zhǎng)”MongoDB征文比賽的獲獎(jiǎng)文章。

責(zé)任編輯:武曉燕 來源: Mongoing 中文社區(qū)
相關(guān)推薦

2016-09-27 21:25:08

Go語言Ken Thompso

2018-12-21 11:26:49

MySQLMongoDB數(shù)據(jù)庫(kù)

2011-06-08 10:30:08

MongoDB

2017-02-27 15:19:04

2021-04-09 09:55:55

DockerGoLinux

2018-09-28 10:06:21

移動(dòng)開發(fā)App

2023-02-10 08:58:46

2017-02-27 15:43:14

iOSObject-CJava

2020-11-16 12:03:08

Java開發(fā)代碼

2019-11-20 10:39:35

iPhone緩存清理

2023-01-12 09:01:01

MongoDBMySQL

2021-08-23 13:25:25

Vue3CSS前端

2021-01-20 14:25:53

Vue3CSS前端

2024-02-05 21:48:25

VueReactHooks

2021-12-27 14:19:44

殺毒軟件病毒電腦安全

2020-06-19 14:55:11

Kubernetes容器技術(shù)

2011-11-28 10:21:52

Nginx特性

2020-04-14 15:54:07

5G物聯(lián)網(wǎng)Wi-Fi

2022-06-14 11:01:48

SpringBootTomcatUndertow

2020-02-13 17:49:55

SpringBoot放棄選擇
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)