MongoDB的最佳實踐是怎樣的,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
從網(wǎng)站建設(shè)到定制行業(yè)解決方案,為提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計服務(wù)體系,各種行業(yè)企業(yè)客戶提供網(wǎng)站建設(shè)解決方案,助力業(yè)務(wù)快速發(fā)展。成都創(chuàng)新互聯(lián)將不斷加快創(chuàng)新步伐,提供優(yōu)質(zhì)的建站服務(wù)。作為MongoDB的一名方案架構(gòu)師,我的大部分時間都是在和MongoDB的客戶和用戶交互。在這里,我希望通過一個不斷更新的活文章的方式來為大家收集整理一下MongoDB開發(fā)及維護時候值得了解或者遵從的一些最佳實踐。我非常真切地希望您也可以參與進來,共同維護這個文檔,讓更多的用戶受惠。
MongoDB服務(wù)器在默認安裝下不啟用鑒權(quán)。這意味著每個人都可以直接連接到mongod實例并執(zhí)行任意數(shù)據(jù)庫操作。建議按照文檔啟用鑒權(quán) http://docs.mongoing.com/manual-zh/tutorial/enable-authentication.html
MongoDB支持按角色定義的權(quán)限系統(tǒng)。你應(yīng)該基于“最少權(quán)限”準則,顯式的為用戶分配僅需要的相應(yīng)權(quán)限。
盡可能使用LDAP、Kerbero之類的中央鑒權(quán)服務(wù)器,并使用強口令策略。
如果你的服務(wù)器有多個網(wǎng)卡,建議只在內(nèi)網(wǎng)的IP上監(jiān)聽服務(wù)。
MongoDB企業(yè)版支持存儲加密,對涉及到客戶的敏感數(shù)據(jù)應(yīng)該使用加密引擎來保護數(shù)據(jù)。
MongoDB的建議最小部署是3個數(shù)據(jù)節(jié)點構(gòu)成的復(fù)制集。復(fù)制集可以提供以下優(yōu)點:
系統(tǒng)99.999% 高可用
自動故障切換
數(shù)據(jù)冗余
容災(zāi)部署
讀寫分離
分片可以用來擴展你系統(tǒng)的讀寫能力,但是分片也會帶來不少新的挑戰(zhàn)比如說管理上的復(fù)雜度,成本的增加,選擇合適片鍵的挑戰(zhàn)性等等。一般來說,你應(yīng)該先窮盡了其他的性能調(diào)優(yōu)的選項以后才開始考慮分片,比如說,索引優(yōu)化,模式優(yōu)化,代碼優(yōu)化,硬件資源優(yōu)化,IO優(yōu)化等。
分片的一些觸發(fā)條件為:
數(shù)據(jù)總量太大,無法在一臺服務(wù)器上管理
并發(fā)量太高,一臺服務(wù)器無法及時處理
磁盤IO壓力太大
單機系統(tǒng)內(nèi)存不夠大,無法裝下熱數(shù)據(jù)
服務(wù)器網(wǎng)卡處理能力達到瓶頸
多地部署情況下希望支持本地化讀寫
取決于你分片的觸發(fā)條件,你可以按照總的需求 然后除以每一臺服務(wù)器的能力來確定所需的分片數(shù)。
分片之間的數(shù)據(jù)互相不復(fù)制。每個分片的數(shù)據(jù)必須在分片內(nèi)保證高可用。因此,對每一個分片MongoDB要求至少部署3個數(shù)據(jù)節(jié)點來保證該分片在絕大部分時間都不會因為主節(jié)點宕機而造成數(shù)據(jù)不可用。
在分片場景下, 最重要的一個考量是選擇合適的片鍵。選擇片鍵需要考慮到應(yīng)用的讀寫模式。通常來說一個片鍵要么是對寫操作優(yōu)化,要么是對讀操作優(yōu)化。要根據(jù)哪種操作更加頻繁而進行相應(yīng)的權(quán)衡。
片鍵值應(yīng)該具有很高的基數(shù),或者說,這個片鍵在集合內(nèi)有很多不同的值,例如_id就是一個基數(shù)很高的片鍵因為_id值不會重復(fù)
片鍵一般不應(yīng)該是持續(xù)增長的,比如說timestamp就是個持續(xù)增長的片鍵。此類片鍵容易造成熱分片現(xiàn)象,即新的寫入集中到某一個分片上
好的片鍵應(yīng)該會讓查詢定向到某一個(或幾個)分片上從而提高查詢效率。一般來說這個意味著片鍵應(yīng)該包括最常用查詢用到的字段
好的片鍵應(yīng)該足夠分散,讓新的插入可以分布到多個分片上從而提高并發(fā)寫入率。
可以使用幾個字段的組合來組成片鍵,以達到幾個不同的目的(基數(shù),分散性,及查詢定向等)
MongoDB是一個高性能高并發(fā)的數(shù)據(jù)庫,其大部分的IO操作為隨機更新。一般來說本機自帶的SSD是最佳的存儲方案。如果使用普通的硬盤,建議使用RAID10條帶化來提高IO通道的并發(fā)能力。
MongoDB很多的性能瓶頸和IO相關(guān)。建議為日志盤(Journal和系統(tǒng)日志)單獨設(shè)定一個物理卷,減少對數(shù)據(jù)盤IO的資源占用。
系統(tǒng)日志可以直接在命令行或者配置文件參數(shù)內(nèi)指定。Journal日志不支持直接指定到另外的目錄,可以通過對Journal目錄創(chuàng)建symbol link的方式來解決。
MongoDB在WiredTiger存儲引擎下建議使用XFS文件系統(tǒng)。Ext4最為常見,但是由于ext文件系統(tǒng)的內(nèi)部journal和WiredTiger有所沖突,所以在IO壓力較大情況下表現(xiàn)不佳。
WiredTiger 對寫操作的落盤是異步發(fā)生的。默認是60秒做一次checkpoint。做checkpoint需要對內(nèi)存內(nèi)所有臟數(shù)據(jù)遍歷以便整理然后把這些數(shù)據(jù)寫入硬盤。如果緩存超大(如大于128G),那么這個checkpoint時間就需要較長時間。在checkpoint期間數(shù)據(jù)寫入性能會受到影響。目前建議實際緩存設(shè)置在64GB或以下。
Transparent Huge Pages (THP) 是Linux的一種內(nèi)存管理優(yōu)化手段,通過使用更大的內(nèi)存頁來減少Translation Lookaside Buffer(TLB)的額外開銷。 MongoDB數(shù)據(jù)庫大部分是比較分散的小量數(shù)據(jù)讀寫,THP對MongoDB這種工況會有負面的影響所以建議關(guān)閉。
http://docs.mongoing.com/manual-zh/tutorial/transparent-huge-pages.html
防止MongoDB 的log文件無限增大,占用太多磁盤空間。好的實踐是啟用log rotation并及時清理歷史日志文件。
http://docs.mongoing.com/manual-zh/tutorial/rotate-log-files.html
足夠的Oplog空間可以保證有足夠的時間讓你從頭恢復(fù)一個從節(jié)點,或者對從節(jié)點執(zhí)行一些比較耗時的維護操作。假設(shè)你最長的下線維護操作需要H小時,那么你的Oplog 一般至少要保證可以保存 H 2 或者 H3 小時的oplog。
如果你的MongoDB部署的時候未設(shè)置正確的Oplog 大小,可以參照下述鏈接來調(diào)整:
http://docs.mongoing.com/manual-zh/tutorial/change-oplog-size.html
禁止系統(tǒng)對文件的訪問時間更新會有效提高文件讀取的性能。這個可以通過在 /etc/fstab 文件中增加 noatime 參數(shù)來實現(xiàn)。例如:
/dev/xvdb /data ext4 noatime 0 0
修改完文件后重新 mount就可以:
# mount -o remount /data
Linux默認的文件描述符數(shù)和大進程數(shù)對于MongoDB來說一般會太低。建議把這個數(shù)值設(shè)為64000。因為MongoDB服務(wù)器對每一個數(shù)據(jù)庫文件以及每一個客戶端連接都需要用到一個文件描述符。如果這個數(shù)字太小的話在大規(guī)模并發(fā)操作情況下可能會出錯或無法響應(yīng)。 你可以通過以下命令來修改這些值:
ulimit -n 64000 ulimit -u 64000
在一個使用NUMA技術(shù)的多處理器Linux 系統(tǒng)上,你應(yīng)該禁止NUMA的使用。MongoDB在NUMA環(huán)境下運行性能有時候會可能變慢,特別是在進程負載很高的情況下。
預(yù)讀值是文件操作系統(tǒng)的一個優(yōu)化手段,大致就是在程序請求讀取一個頁面的時候,文件系統(tǒng)會同時讀取下面的幾個頁面并返回。這原因是因為很多時候IO最費時的磁盤尋道。通過預(yù)讀,系統(tǒng)可以提前把緊接著的數(shù)據(jù)同時返回。假設(shè)程序是在做一個連續(xù)讀的操作,那么這樣可以節(jié)省很多磁盤尋道時間。
MongoDB很多時候會做隨機訪問。對于隨機訪問,這個預(yù)讀值應(yīng)該設(shè)置的較小為好.一般來說32是一個不錯的選擇。
你可以使用下述命令來顯示當前系統(tǒng)的預(yù)讀值:
sudo blockdev --report
要更改預(yù)讀值,可以用以下命令:
sudo blockdev --setra 32
把 換成合適的存儲設(shè)備。
在使用MongoDB復(fù)制集或者分片集群的時候,注意一定要使用NTP時間服務(wù)器。這樣可以保證MongoDB集群成原則之間正確同步。
關(guān)鍵的指標包括:
Disk Space 磁盤空間
CPU
RAM 使用率
Ops Counter 增刪改查
Replication Lag 復(fù)制延遲
Connections 連接數(shù)
Oplog Window
默認情況下MongoDB會在日志文件中(mongod.log)記錄超過100ms的數(shù)據(jù)庫操作。
這個是針對于數(shù)據(jù)量較大比如說超過幾十上百萬(文檔數(shù)目)數(shù)量級的集合。如果沒有索引MongoDB需要把所有的Document從盤上讀到內(nèi)存,這會對MongoDB服務(wù)器造成較大的壓力并影響到其他請求的執(zhí)行。
如果你的查詢會使用到多個字段,MongoDB有兩個索引技術(shù)可以使用:交叉索引和組合索引。交叉索引就是針對每個字段單獨建立一個單字段索引,然后在查詢執(zhí)行時候使用相應(yīng)的單字段索引進行索引交叉而得到查詢結(jié)果。交叉索引目前觸發(fā)率較低,所以如果你有一個多字段查詢的時候,建議使用組合索引能夠保證索引正常的使用。
例如,如果應(yīng)用需要查找所有年齡小于30歲的深圳市馬拉松運動員:
db.athelets.find({sport: "marathon", location: "sz", age: {$lt: 30}}})
那么你可能需要這樣的一個索引:
db.athelets.ensureIndex({sport:1, location:1, age:1});
以上文為例子,在創(chuàng)建組合索引時如果條件有匹配和范圍之分,那么匹配條件(sport: “marathon”) 應(yīng)該在組合索引的前面。范圍條件(age: <30)字段應(yīng)該放在組合索引的后面。
有些時候你的查詢只需要返回很少甚至只是一個字段,例如,希望查找所有虹橋機場出發(fā)的所有航班的目的地。已有的索引是:
{origin: 1, dest: 1}
如果正常的查詢會是這樣(只需要返回目的地機場):
db.flights.find({origin:"hongqiao"}, {dest:1});
這樣的查詢默認會包含_id 字段,所以需要掃描匹配的文檔并取回結(jié)果。相反,如果使用這個查詢語句:
db.flights.find({origin:"hongqiao"}, {_id:0, dest:1});
MongoDB則可以直接從索引中取得所有需要返回的值,而無需掃描實際文檔(文檔可能需要從硬盤里調(diào)入到內(nèi)存)
在對一個集合創(chuàng)建索引時,該集合所在的數(shù)據(jù)庫將不接受其他讀寫操作。對數(shù)據(jù)量的集合建索引,建議使用后臺運行選項 {background: true}
MongoDB可以讓你像關(guān)系型數(shù)據(jù)庫一樣設(shè)計表結(jié)構(gòu),但是它不支持外鍵,也不支持復(fù)雜的Join!如果你的程序發(fā)現(xiàn)有大量實用JOIN的地方,那你的設(shè)計可能需要重新來過。參照以下相關(guān)模式設(shè)計建議。
MongoDB的模式設(shè)計基于靈活豐富的JSON文檔模式。在很多情況下,一個MongoDB應(yīng)用的數(shù)據(jù)庫內(nèi)的集合(表)的數(shù)量應(yīng)該遠遠小于使用關(guān)系數(shù)據(jù)庫的同類型應(yīng)用。MongoDB表設(shè)計不遵從第三范式。MongoDB的數(shù)據(jù)模型非常接近于對象模型,所以基本上就是按照主要的Domain object的數(shù)量來建相應(yīng)的集合。根據(jù)經(jīng)驗,一般小型應(yīng)用的集合數(shù)量通常在幾個之內(nèi),中大型的應(yīng)用會在10多個或者最多幾十個。
MongoDB模式設(shè)計不能按照第三范式,很多時候允許數(shù)據(jù)在多個文檔中重復(fù),比如說,在每一個員工的文檔中重復(fù)他的部門名字,就是一個可以接受的做法。如果部門名字改了,可以執(zhí)行一個update({},{}, {multi:true}) 的多文檔更新來一次性把部門名字更新掉。
一般來說,如果某個字段的數(shù)據(jù)值經(jīng)常會變,則不太適合被大量冗余到別的文檔或者別的集合里面去。舉例來說,如果我們是在做一些股票類型資產(chǎn)管理, 可能有很多人都購買了Apple的股票,但是如果把經(jīng)常變動的股價冗余到客戶的文檔里,由于股票價格變動頻繁,會導(dǎo)致有大量的更新操作。從另外一個角度來說,如果是一些不經(jīng)常變的字段,如客戶的姓名,地址,部門等,則可以盡管進行冗余shi’yang
對于一對多的關(guān)系,如一個人有幾個聯(lián)系方式,一本書有10幾個章節(jié),等等,建議使用內(nèi)嵌方式,把N的數(shù)據(jù)以數(shù)組形式來描述,如:
> db.person.findOne() { user_id: 'tjworks', name: 'TJ Tang', contact : [ { type: 'mobile', number: '1856783691' }, { type: 'wechat', number: 'tjtang826'} ] }
有些時候這個一對多的多端數(shù)量較大, 比如說,一個部門內(nèi)有多少員工。在華為一個三級部門可能有數(shù)千員工,這個時候如果把所有員工信息直接內(nèi)嵌到部門內(nèi)肯定不是個好的選擇,有可能會超出16MB的文檔限制。這個時候可以采用引用ID的方式:
> db.departments.findOne() { name : 'Enterprise BG', president: 'Zhang San', employees : [ // array of references to Employee colletion ObjectID('AAAA'), ObjectID('F17C'), ObjectID('D2AA'), // etc ] }
如果需要查詢部門下員工相關(guān)信息,你可以使用$lookup聚合操作符來把員工信息進行關(guān)聯(lián)并返回。
如果一對多情況下,這個多端數(shù)量無限大并會頻繁增長,比如說,一個測量儀的每分鐘讀數(shù),一年下來有幾十萬條,這個時候即使是把ID放到數(shù)組里都會管理不便,這個時候就應(yīng)該把多端的數(shù)據(jù)創(chuàng)建一個集合,并在那個集合的文檔里加入對主文檔的連接引用,如:
> db.sensors.findOne() { _id : ObjectID('AAAB'), name : 'engine temperature', vin : '4GD93039GI239', engine_id: '20394802', manuafacture: 'First Motor', production_date: '2014-02-01' ... } >db.readings.findOne() { time : ISODate("2014-03-28T09:42:41.382Z"), sensor: ObjectID('AAAB'), reading: 67.4 }
如果你有需要把PDF文件,圖片,甚至小視頻等二進制文件需要管理,建議使用MongoDB 的GridFS API 或者自己手動分集合來分開管理二進制數(shù)據(jù)和元數(shù)據(jù)。
數(shù)組是用來表達 1對多關(guān)系的利器,但是MongoDB對嵌套的數(shù)組內(nèi)元素缺乏直接更新能力。比如說:
{ name: "Annice", courses: [ { name: "English", score: 97 }, { name: "Math", score: 89 }, { name: "Physics", score: 95 } ] }
這樣設(shè)計沒有嵌套數(shù)組,我們可以直接對 Math的score 修改為99:
db.students.update({name: "Annice", "courses.name":"Math"}, {$set:{"courses.$.score": 99 }})
注意數(shù)組定位符 $的用法, 的用法,$ 表示當前匹配的第一個數(shù)組元素的在數(shù)組內(nèi)的索引。
但是下面這種情況就涉及到了數(shù)組嵌套:
{ name: "Annice", courses: [ { name: "Math", scores: [ {term: 1, score: 80} , {term: 2, score: 90} ] }, { name: "Physics", score: 95 } ] }
這個時候如果你想對Math course的term 1的Score進行修改,你就需要把 scores 這個數(shù)組整個調(diào)到內(nèi)存然后在代碼里對這個嵌套數(shù)組的元素進行修改。這是因為MongoDB的數(shù)組定位符 $ 只對第一層數(shù)組有效。
當然,如果你的模型不需要修改嵌套的數(shù)組內(nèi)元素,那么這條就不適用。
Java驅(qū)動的默認連接池大小是100。建議按照應(yīng)用的實際情況做調(diào)整。對壓力較小的應(yīng)用可以適當調(diào)小減少對應(yīng)用服務(wù)器的資源占用。
MongoDB的建議最小部署是一個復(fù)制集,包含3個數(shù)據(jù)節(jié)點。默認情況下應(yīng)用的寫操作(更新,插入或者刪除)在主節(jié)點上完成后就會立即返回。寫操作則通過OPLOG方式在后臺異步方式復(fù)制到其他節(jié)點。在極端情況下,這些寫操作可能還未在復(fù)制到從節(jié)點的時候主節(jié)點就出現(xiàn)宕機。這個時候發(fā)生主備節(jié)點切換,原主節(jié)點的寫操作會被回滾到文件而對應(yīng)用不可見。為防止這種情況出現(xiàn),MongoDB建議對重要的數(shù)據(jù)使用 {w: “marjority”} 的選項。{w: “majority”} 可以保證數(shù)據(jù)在復(fù)制到多數(shù)節(jié)點后才返回成功結(jié)果。使用該機制可以有效防止數(shù)據(jù)回滾的發(fā)生。
另外你可以使用 {j:1} (可以和 w:”majrotiy” 結(jié)合使用) 來指定數(shù)據(jù)必須在寫入WAL日志之后才向應(yīng)用返回成功確認。這個會導(dǎo)致寫入性能有所下降,但是對于重要的數(shù)據(jù)可以考慮使用。
MongoDB由于是一個分布式系統(tǒng),一份數(shù)據(jù)會在多個節(jié)點上進行復(fù)制。從哪個節(jié)點上讀數(shù)據(jù),要根據(jù)應(yīng)用讀數(shù)據(jù)的需求而定。以下是集中可以配置的讀選項:
primary: 默認,在主節(jié)點上讀數(shù)據(jù)
priaryPreferred: 先從主節(jié)點上讀,如果為成功再到任意一臺從節(jié)點上讀
secondary: 在從節(jié)點上讀數(shù)據(jù)(當有多臺節(jié)點的時候,隨機的使用某一臺從節(jié)點)
secondaryPreferred: 首先從從節(jié)點上讀,如果從節(jié)點由于某種原因不能提供服務(wù),則從主節(jié)點上進行讀
nearest: 從距離最近的節(jié)點來讀。距離由ping操作的時間來決定。
除第一個選項之外,其他讀選項都存在讀到的數(shù)據(jù)不是最新的可能。原因是數(shù)據(jù)的復(fù)制是后臺異步完成的。
MongoClient是個線程安全的類,自帶線程池。通常在一個JVM內(nèi)不要實例化多個MongoClient實例,避免連接數(shù)過多和資源的不必要浪費。
MongoDB使用復(fù)制集技術(shù)可以實現(xiàn)99.999%的高可用。當一臺主節(jié)點不能寫入時,系統(tǒng)會自動故障轉(zhuǎn)移到另一臺節(jié)點。轉(zhuǎn)移可能會耗時幾秒鐘,在這期間應(yīng)用應(yīng)該捕獲相應(yīng)的Exception并執(zhí)行重試操作。重試應(yīng)該有backoff機制,例如,分別在1s,2s,4s,8s等時候進行重試。
MongoDB 沒有表結(jié)構(gòu)定義。每個文檔的結(jié)構(gòu)由每個文檔內(nèi)部的字段決定。所有字段名會在每個文檔內(nèi)重復(fù)。使用太長的字段名字會導(dǎo)致對內(nèi)存、網(wǎng)絡(luò)帶寬更多的需求。(由于壓縮技術(shù),長字段名對硬盤上的存儲不會有太多占用)
如: School, Course, StudentRecord
或者:school, course, stuent_record
不要把MongoDB和普通的鍵值型數(shù)據(jù)庫(KV)視為等同。MongoDB支持和關(guān)系型數(shù)據(jù)庫update語句類似的in place update。你只需要在update語句中指定需要更新的字段,而不是整個文檔對象。
舉例來說,加入我想把用戶的名字從TJ改為Tang Jianfa.
不建議的做法:
user = db.users.findOne({_id: 101}); user.name="Tang Jianfa" db.users.save(user);
建議的做法:
user = db.users.findOne({_id: 101}); // do certain things db.users.update({_id:101}, {$set: {name: "Tang Jianfa"}});
MongoDB 支持類似于SQL語句里面的select,可以對返回的字段進行過濾。使用Projection可以減少返回的內(nèi)容,降低網(wǎng)絡(luò)傳輸?shù)牧亢痛a中轉(zhuǎn)化成對象所需的時間。
很多時候我們用MongoDB來存儲一些時效性的數(shù)據(jù),如7天的監(jiān)控數(shù)據(jù)。與其自己寫個后臺腳本定期清理過期數(shù)據(jù),你可以使用TTL索引來讓MongoDB自動刪除過期數(shù)據(jù):
db.data.ensureIndex({create_time:1}, {expireAfterSeconds: 7*24*3600})
有些時候你不知道一條文檔數(shù)據(jù)是否已經(jīng)在庫里存在。這個時候你要么先查詢一下,要么就是使用upsert語句。在SpringData下面upsert語句需要你把每個字段的值都在upsert語句中格式化出來。字段多的時候未免有些繁瑣。SpringData MongoDB里面的MongoTemplate有個execute方法可以用來實現(xiàn)一個DB調(diào)用,也不用繁瑣的把所有字段羅列出來的例子。
public boolean persistEmployee(Employee employee) throws Exception { BasicDBObject dbObject = new BasicDBObject(); mongoTemplate.getConverter().write(employee, dbObject); mongoTemplate.execute(Employee.class, new CollectionCallback
SpringData MongoDB默認會在MongoDB文檔中添加一個_class字段,里面保存的是fully qualified class name, 如”com.mongodb.examples.Customer”。對于有些小文檔來說,這個字段可能會占據(jù)不小一部分的存儲空間。如果你不希望SpringData 自動加入這個字段,你可以:
1) 自定義MongoTypeMapper
@Bean public MongoTemplate mongoTemplate() throws UnknownHostException { MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(new DefaultDbRefResolver (mongoDbFactory()), new MongoMappingContext()); mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null)); return new MongoTemplate(mongoDbFactory(), mappingMongoConverter ); }
2) 在使用find語句時,顯式地指定類的名字/類型:
MongoTemplate.find(new Query(), Inventory.class))
看完上述內(nèi)容,你們掌握MongoDB的最佳實踐是怎樣的的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站制作公司行業(yè)資訊頻道,感謝各位的閱讀!
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準確進行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務(wù)器買多久送多久。