TiDB(NewSQL)

1. TiDB介紹

TiDB 是分布式關(guān)系型數(shù)據(jù)庫(kù)驳糯,是一款同時(shí)支持在線事務(wù)處理與在線分析處理的融合型分布式數(shù)據(jù)庫(kù)產(chǎn)品东抹,具備水平擴(kuò)容或者縮容帕识、金融級(jí)高可用潜腻、云原生的分布式數(shù)據(jù)庫(kù)窍育、兼容 MySQL 5.7 協(xié)議和 MySQL 生態(tài)等重要特性。目標(biāo)是為用戶提供一站式 OLTP (Online Transactional Processing)宴胧、OLAP (Online Analytical Processing)漱抓。TiDB 適合高可用、強(qiáng)一致要求較高恕齐、數(shù)據(jù)規(guī)模較大等各種應(yīng)用場(chǎng)景乞娄。TiBD也是NewSQL的一種。

OLTP:聯(lián)機(jī)的事務(wù)處理显歧,特點(diǎn)是在短時(shí)間內(nèi)返回查詢結(jié)果仪或,對(duì)應(yīng)的是關(guān)系型數(shù)據(jù)庫(kù),例如mysql追迟,sqlserver溶其,oracle等骚腥,底層使用的innodb引擎敦间,B+ 樹等數(shù)據(jù)結(jié)構(gòu)。

OLAP:聯(lián)機(jī)的分析處理束铭,特點(diǎn)是對(duì)歷史數(shù)據(jù)分析廓块,然后產(chǎn)生決策性的影響(大數(shù)據(jù)分析),對(duì)應(yīng)的是數(shù)據(jù)庫(kù)契沫,例如HIVE(數(shù)據(jù)倉(cāng)庫(kù))带猴,Hbase。

關(guān)系型數(shù)據(jù)庫(kù)(SQL):

缺點(diǎn):

  1. 不支持在線的數(shù)據(jù)庫(kù)擴(kuò)容懈万,縮容拴清。
  2. 大量數(shù)據(jù)查詢非常慢
  3. 并發(fā)能力差(使用集群,分庫(kù)会通,分表口予,mycat 實(shí)現(xiàn)但是成本較大)

優(yōu)點(diǎn):

  1. 關(guān)系型數(shù)據(jù)庫(kù)

非關(guān)系型數(shù)據(jù)庫(kù)(NOSQL):

缺點(diǎn):

  1. 致命缺點(diǎn)丟失數(shù)據(jù)
  2. 不能聯(lián)查

優(yōu)點(diǎn):

  1. 性能高
  2. 并發(fā)能力強(qiáng)
  3. 支持在線的數(shù)據(jù)庫(kù)擴(kuò)容,縮容

NewSQL:結(jié)合了關(guān)系型和非關(guān)系型數(shù)據(jù)庫(kù)的優(yōu)勢(shì)可以做到以下

  1. 并發(fā)能力高
  2. 支持在線的數(shù)據(jù)庫(kù)擴(kuò)容涕侈,縮容
  3. 支持云原生
  4. 可以聯(lián)查

2. 架構(gòu)解析

20190225192015447.png
  • TiDB Server:SQL 層沪停,對(duì)外暴露 MySQL 協(xié)議的連接 endpoint,負(fù)責(zé)接受客戶端的連接裳涛,執(zhí)行 SQL 解析和優(yōu)化木张,最終生成分布式執(zhí)行計(jì)劃。TiDB 層本身是無(wú)狀態(tài)的端三,實(shí)踐中可以啟動(dòng)多個(gè) TiDB 實(shí)例舷礼,通過(guò)負(fù)載均衡組件(如 LVS、HAProxy 或 F5)對(duì)外提供統(tǒng)一的接入地址郊闯,客戶端的連接可以均勻地分?jǐn)傇诙鄠€(gè) TiDB 實(shí)例上以達(dá)到負(fù)載均衡的效果妻献。TiDB Server 本身并不存儲(chǔ)數(shù)據(jù)浮声,只是解析 SQL,將實(shí)際的數(shù)據(jù)讀取請(qǐng)求轉(zhuǎn)發(fā)給底層的存儲(chǔ)節(jié)點(diǎn) TiKV(或 TiFlash)旋奢。
  • PD (Placement Driver) Server:整個(gè) TiDB 集群的元信息管理模塊泳挥,負(fù)責(zé)存儲(chǔ)每個(gè) TiKV 節(jié)點(diǎn)實(shí)時(shí)的數(shù)據(jù)分布情況和集群的整體拓?fù)浣Y(jié)構(gòu),提供 TiDB Dashboard 管控界面至朗,并為分布式事務(wù)分配事務(wù) ID屉符。PD 不僅存儲(chǔ)元信息,同時(shí)還會(huì)根據(jù) TiKV 節(jié)點(diǎn)實(shí)時(shí)上報(bào)的數(shù)據(jù)分布狀態(tài)锹引,下發(fā)數(shù)據(jù)調(diào)度命令給具體的 TiKV 節(jié)點(diǎn)矗钟,可以說(shuō)是整個(gè)集群的“大腦”。此外嫌变,PD 本身也是由至少 3 個(gè)節(jié)點(diǎn)構(gòu)成,擁有高可用的能力腾啥。建議部署奇數(shù)個(gè) PD 節(jié)點(diǎn)。
  • 存儲(chǔ)節(jié)點(diǎn)
    • TiKV Server:負(fù)責(zé)存儲(chǔ)數(shù)據(jù)疮跑,從外部看 TiKV 是一個(gè)分布式的提供事務(wù)的 Key-Value 存儲(chǔ)引擎。存儲(chǔ)數(shù)據(jù)的基本單位是 Region凸舵,每個(gè) Region 負(fù)責(zé)存儲(chǔ)一個(gè) Key Range(從 StartKey 到 EndKey 的左閉右開(kāi)區(qū)間)的數(shù)據(jù)祖娘,每個(gè) TiKV 節(jié)點(diǎn)會(huì)負(fù)責(zé)多個(gè) Region啊奄。TiKV 的 API 在 KV 鍵值對(duì)層面提供對(duì)分布式事務(wù)的原生支持,默認(rèn)提供了 SI (Snapshot Isolation) 的隔離級(jí)別菇夸,這也是 TiDB 在 SQL 層面支持分布式事務(wù)的核心琼富。TiDB 的 SQL 層做完 SQL 解析后,會(huì)將 SQL 的執(zhí)行計(jì)劃轉(zhuǎn)換為對(duì) TiKV API 的實(shí)際調(diào)用公黑。所以摄咆,數(shù)據(jù)都存儲(chǔ)在 TiKV 中。另外朝蜘,TiKV 中的數(shù)據(jù)都會(huì)自動(dòng)維護(hù)多副本(默認(rèn)為三副本)涩金,天然支持高可用和自動(dòng)故障轉(zhuǎn)移暇仲。
    • TiFlash:TiFlash 是一類特殊的存儲(chǔ)節(jié)點(diǎn)副渴。和普通 TiKV 節(jié)點(diǎn)不一樣的是煮剧,在 TiFlash 內(nèi)部,數(shù)據(jù)是以列式的形式進(jìn)行存儲(chǔ)勉盅,主要的功能是為分析型的場(chǎng)景加速草娜。

TiDB的搭建

  1. 操作系統(tǒng)


    8.png
  2. 搭建條件

    TiDB 支持部署和運(yùn)行在 Intel x86-64 架構(gòu)的 64 位通用硬件服務(wù)器平臺(tái)或者 ARM 架構(gòu)的硬件服務(wù)器平臺(tái)。對(duì)于開(kāi)發(fā)茬贵,測(cè)試议蟆,及生產(chǎn)環(huán)境的服務(wù)器硬件配置(不包含操作系統(tǒng) OS 本身的占用)有以下要求和建議:

7.png
  1. 下載文件
#克隆安裝腳本闷沥,或者直接復(fù)制下載好的文件內(nèi)容(下載所有的腳本到,然后把整個(gè)復(fù)制到指定的目錄下)
git clone https://github.com/pingcap/tidb-docker-compose.git

#執(zhí)行docker-compose之前先需要清除本機(jī)掛載蚂维,如果之前安裝過(guò)
docker volume rm $(docker volume ls -q)
#安裝
docker-compose up -d


#設(shè)置密碼
set password for 'root'@'%' = '123456';

搭建成功可用mysql工具軟件連接測(cè)試虫啥,以后就可以如同mysql一樣使用了。

同時(shí)可以使用http:IP:3000 查看數(shù)據(jù)庫(kù)的狀態(tài)

4. 數(shù)據(jù)的一致性

1. 選舉

節(jié)點(diǎn)是可以自己給自己投票的苹祟,啟動(dòng)的時(shí)候獲得了大多數(shù)的票的就會(huì)作為leader评雌,當(dāng)出現(xiàn)投票一致的時(shí)候,就會(huì)進(jìn)行重新的選舉砂轻。

2. 日志復(fù)制

從客戶端來(lái)的數(shù)據(jù)斤吐,先是主節(jié)點(diǎn)收到數(shù)據(jù),主節(jié)點(diǎn)把數(shù)據(jù)通過(guò)raft協(xié)議把日志發(fā)送到所有的從節(jié)點(diǎn)庄呈。當(dāng)超過(guò)半數(shù)(包括半數(shù))的從節(jié)點(diǎn)返回ack 后诬留,主節(jié)點(diǎn)認(rèn)為數(shù)據(jù)保存落盤 。然后傀广,繼續(xù)做1.返回給客戶端ack 數(shù)據(jù)收到彩届,當(dāng)返回客戶端成功后,主節(jié)點(diǎn)然后通知從節(jié)點(diǎn)贮聂,把上次的數(shù)據(jù)改為提交狀態(tài)(提交狀態(tài)的數(shù)據(jù)寨辩,才能被查詢到)。至于沒(méi)有給主節(jié)點(diǎn)返回ack的從節(jié)點(diǎn)耻警,主節(jié)點(diǎn)會(huì)重復(fù)給這些從節(jié)點(diǎn)日志復(fù)制甘穿。

如果梢杭,主機(jī)點(diǎn)和其他的從節(jié)點(diǎn)網(wǎng)絡(luò)斷開(kāi),則客戶端會(huì)寫入數(shù)據(jù)失敗募判,其他的從節(jié)點(diǎn)會(huì)從新的選舉主節(jié)點(diǎn)咒唆,保證后面的數(shù)據(jù)能寫入成功。經(jīng)過(guò)一段時(shí)間舊的主節(jié)點(diǎn)從新連接上來(lái)后敦腔,舊 的主節(jié)點(diǎn)會(huì)對(duì)寫入失敗的數(shù)據(jù)做回滾恨溜,然后作為新的主節(jié)點(diǎn)的從節(jié)點(diǎn),同步新的主節(jié)點(diǎn)的數(shù)據(jù)判族。

注意:當(dāng)網(wǎng)絡(luò)不是很好的時(shí)候形帮,已經(jīng)產(chǎn)生了新的主節(jié)點(diǎn)。新的客戶端對(duì)舊的數(shù)據(jù)做修改操作后界斜。會(huì)造成舊的客戶端連接舊的主節(jié)點(diǎn)對(duì)查出來(lái)的數(shù)據(jù)是舊的合冀。

5. 對(duì)接Spark引擎大數(shù)據(jù)查詢

1. Spark介紹

Apache Spark是專為大規(guī)模數(shù)據(jù)處理而設(shè)計(jì)的快速通用的計(jì)算引擎 。現(xiàn)在形成一個(gè)高速發(fā)展應(yīng)用廣泛的生態(tài)系統(tǒng)峭判。

Spark 主要有三個(gè)特點(diǎn) :

首先林螃,高級(jí) API 剝離了對(duì)集群本身的關(guān)注俺泣,Spark 應(yīng)用開(kāi)發(fā)者可以專注于應(yīng)用所要做的計(jì)算本身。

其次侮邀,Spark 很快贝润,支持交互式計(jì)算和復(fù)雜算法铝宵。

最后鹏秋,Spark 是一個(gè)通用引擎,可用它來(lái)完成各種各樣的運(yùn)算横朋,包括 SQL 查詢百拓、文本處理晰甚、機(jī)器學(xué)習(xí)等厕九,而在 Spark 出現(xiàn)之前地回,我們一般需要學(xué)習(xí)各種各樣的引擎來(lái)分別處理這些需求。

  • 更快的速度

內(nèi)存計(jì)算下畅买,Spark 比 Hadoop 快100倍谷羞。

  • 易用性

Spark 提供了80多個(gè)高級(jí)運(yùn)算符纹冤。

  • 通用性

Spark 提供了大量的庫(kù),包括Spark Core雁歌、Spark SQL知残、Spark Streaming求妹、MLlib、GraphX父能。 開(kāi)發(fā)者可以在同一個(gè)應(yīng)用程序中無(wú)縫組合使用這些庫(kù)净神。

  • 支持多種資源管理器

Spark 支持 Hadoop YARN,Apache Mesos爱榕,及其自帶的獨(dú)立集群管理器

  • Spark生態(tài)系統(tǒng)
  • Shark:Shark基本上就是在Spark的框架基礎(chǔ)上提供和Hive一樣的HiveQL命令接口黔酥,為了最大程度的保持和Hive的兼容性,Spark使用了Hive的API來(lái)實(shí)現(xiàn)query Parsing和 Logic Plan generation棵帽,最后的PhysicalPlan execution階段用Spark代替HadoopMapReduce坑夯。通過(guò)配置Shark參數(shù)柜蜈,Shark可以自動(dòng)在內(nèi)存中緩存特定的RDD,實(shí)現(xiàn)數(shù)據(jù)重用淑履,進(jìn)而加快特定數(shù)據(jù)集的檢索秘噪。同時(shí),Shark通過(guò)UDF用戶自定義函數(shù)實(shí)現(xiàn)特定的數(shù)據(jù)分析學(xué)習(xí)算法蹋偏,使得SQL數(shù)據(jù)查詢和運(yùn)算分析能結(jié)合在一起至壤,最大化RDD的重復(fù)使用像街。
  • SparkR:SparkR是一個(gè)為R提供了輕量級(jí)的Spark前端的R包。 SparkR提供了一個(gè)分布式的data frame數(shù)據(jù)結(jié)構(gòu)脓斩,解決了 R中的data frame只能在單機(jī)中使用的瓶頸畴栖,它和R中的data frame 一樣支持許多操作吗讶,比如select,filter,aggregate等等。(類似dplyr包中的功能)這很好的解決了R的大數(shù)據(jù)級(jí)瓶頸問(wèn)題。 SparkR也支持分布式的機(jī)器學(xué)習(xí)算法纵寝,比如使用MLib機(jī)器學(xué)習(xí)庫(kù)。 [4] SparkR為Spark引入了R語(yǔ)言社區(qū)的活力葬凳,吸引了大量的數(shù)據(jù)科學(xué)家開(kāi)始在Spark平臺(tái)上直接開(kāi)始數(shù)據(jù)分析之旅室奏。

Hadoop:核心思想是分而治之。其中有三個(gè)組件:

  1. hdfs:分部署的儲(chǔ)存
  2. mapduce:由map 和duce 組成昌简。
  3. 容器纯赎,任務(wù)執(zhí)行容器南蹂,方便垃圾回收,管理分配所有節(jié)點(diǎn)的資源晚顷,也是資源調(diào)度器该默。

以下是hadoop 下的一個(gè)節(jié)點(diǎn)的結(jié)構(gòu):


4.png

Hadoop和數(shù)據(jù)庫(kù)結(jié)構(gòu)就變成了以下?tīng)顟B(tài):


5.png

hadoop 存在的問(wèn)題就是性能低:主要原因就是原始數(shù)據(jù)通過(guò)map從新保存到磁盤中权均,做排序后reduce又從新的從硬盤讀取從新放入磁盤锅锨。

所以現(xiàn)在開(kāi)發(fā)出了spark在內(nèi)存中對(duì)數(shù)據(jù)做匯總以提高它的性能:

以下是結(jié)構(gòu)體


6.png

2. Spark的使用

docker exec -it tidb-docker-compose_tispark-master_1 /bin/bash

cd /opt/spark/data/tispark-sample-data
//插入測(cè)試數(shù)據(jù)
mysql --local-infile=1 -h IP -P 4000 -u root -p123456 < dss.ddl

插入數(shù)據(jù)成功:

可以通過(guò)mysql 數(shù)據(jù)庫(kù)查看到數(shù)據(jù)數(shù)據(jù)庫(kù)


1.png

使用shark查詢數(shù)據(jù):

cd /opt/spark/bin
#啟動(dòng)shell 窗口必指,會(huì)加載一些組件
./spark-shell
#導(dǎo)入組件
import org.apache.spark.sql.TiContext
#定義對(duì)象
var ti=new TiContext(spark)
#定義參數(shù)
ti.tidbMapDatabase("TPCH_001")
spark.sql("select count(*) from lineitem").show

 spark.sql(
      """select
        |   l_returnflag,
        |   l_linestatus,
        |   sum(l_quantity) as sum_qty,
        |   sum(l_extendedprice) as sum_base_price,
        |   sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
        |   sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
        |   avg(l_quantity) as avg_qty,
        |   avg(l_extendedprice) as avg_price,
        |   avg(l_discount) as avg_disc,
        |   count(*) as count_order
        |from
        |   lineitem
        |where
        |   l_shipdate <= date '1998-12-01' - interval '90' day
        |group by
        |   l_returnflag,
        |   l_linestatus
        |order by
        |   l_returnflag,
        |   l_linestatus
      """.stripMargin).show

以下是查詢的結(jié)果:


3.png

注意:

  1. spark 現(xiàn)在存在的問(wèn)題吃內(nèi)存塔橡,
  2. 穩(wěn)定性待測(cè)試

6. 處理大數(shù)據(jù)

為了提升數(shù)據(jù)的讀寫性能TiDB對(duì)硬盤做了分塊葛家,并且分配的磁盤是遞增增加:如下圖:


2.png

數(shù)據(jù)寫入:當(dāng)數(shù)據(jù)寫入時(shí)泌类,首先寫入內(nèi)存中,同時(shí)追加到日志中双仍,當(dāng)把分配的內(nèi)存寫滿后桌吃,把數(shù)據(jù)轉(zhuǎn)移到較小的磁盤中。然后刪除日志文件逗物,當(dāng)較小的磁盤寫滿后轉(zhuǎn)存到較大的磁盤中让簿,以此類推

數(shù)據(jù)修改刪除:刪除的數(shù)據(jù)會(huì)記錄版本號(hào)尔当,處理還是按照日志追加,同理修改記錄也會(huì)進(jìn)入磁盤锐帜,LSM樹TiDB的底層會(huì)做處理畜号。

數(shù)據(jù)讀取:開(kāi)始先讀取內(nèi)存蛮拔,如果內(nèi)存沒(méi)有就找較小的磁盤痹升,較小的磁盤沒(méi)有找較大的磁盤疼蛾,以此類推。為了提升性能衍慎,減少對(duì)磁盤的查詢皮钠,增加了布隆過(guò)濾器麦轰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末期虾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喳坠,更是在濱河造成了極大的恐慌壕鹉,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件负乡,死亡現(xiàn)場(chǎng)離奇詭異抖棘,居然都是意外死亡狸涌,警方通過(guò)查閱死者的電腦和手機(jī)帕胆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)芙盘,“玉大人脸秽,你說(shuō)我怎么就攤上這事豹储。” “怎么了巩剖?”我有些...
    開(kāi)封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵佳魔,是天一觀的道長(zhǎng)晦炊。 經(jīng)常有香客問(wèn)我宁脊,道長(zhǎng)榆苞,這世上最難降的妖魔是什么霞捡? 我笑而不...
    開(kāi)封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任碧信,我火速辦了婚禮,結(jié)果婚禮上躏筏,老公的妹妹穿的比我還像新娘趁尼。我一直安慰自己碴卧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布婶博。 她就那樣靜靜地躺著凡人,像睡著了一般叹阔。 火紅的嫁衣襯著肌膚如雪耳幢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天启上,我揣著相機(jī)與錄音店印,去河邊找鬼按摘。 笑死纫谅,一個(gè)胖子當(dāng)著我的面吹牛付秕,可吹牛的內(nèi)容都是我干的发魄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼口柳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了嵌削?” 一聲冷哼從身側(cè)響起望艺,我...
    開(kāi)封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤找默,失蹤者是張志新(化名)和其女友劉穎惩激,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顷蟀,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸣个,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年布朦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喝滞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡做盅,死狀恐怖吹榴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帅刀,我是刑警寧澤远剩,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布瓜晤,位于F島的核電站,受9級(jí)特大地震影響痢掠,放射性物質(zhì)發(fā)生泄漏驱犹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一足画、第九天 我趴在偏房一處隱蔽的房頂上張望雄驹。 院中可真熱鬧,春花似錦淹辞、人聲如沸医舆。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)彬向。三九已至,卻和暖如春娃胆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背等曼。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工里烦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人禁谦。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓胁黑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親州泊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丧蘸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容