天天看點

centos 安裝mongodb叢集-分片

mongodb叢集有三種方式

    1,主從模式,類似mysql master slave方式。

    2,副本集模式,其實是一主多從,如果主節點挂掉,會重新在從節點選取一台為主節點。

    3,分片模式,針對大資料量,高負載情況。

mysql要做到自動擴充需要加一個資料通路層用程式去擴充,資料庫的增加、删除、備份還需要程式去控制。一但資料庫的節點一多,要維護起來也是非常頭疼的。不過mongodb所有的這一切通過他自己的内部機制就可以搞定!頓時石化了,這麼牛X!還是上圖看看mongodb通過哪些機制實作路由、分片:

<a href="http://s3.51cto.com/wyfs02/M02/6B/65/wKioL1UsvwCgUF0jAAG8apv8TOY057.jpg" target="_blank"></a>

從圖中可以看到有四個元件:mongos、config server、shard、replica set。

mongos,資料庫叢集請求的入口,所有的請求都通過mongos進行協調,不需要在應用程式添加一個路由選擇器,mongos自己就是一個請求分發中心,它負責把對應的資料請求請求轉發到對應的shard伺服器上。在生産環境通常有多mongos作為請求的入口,防止其中一個挂掉所有的mongodb請求都沒有辦法操作。

config server,顧名思義為配置伺服器,存儲所有資料庫元資訊(路由、分片)的配置。mongos本身沒有實體存儲分片伺服器和資料路由資訊,隻是緩存在記憶體裡,配置伺服器則實際存儲這些資料。mongos第一次啟動或者關掉重新開機就會從 config server 加載配置資訊,以後如果配置伺服器資訊變化會通知到所有的 mongos 更新自己的狀态,這樣 mongos 就能繼續準确路由。在生産環境通常有多個 config server 配置伺服器,因為它存儲了分片路由的中繼資料,這個可不能丢失!就算挂掉其中一台,隻要還有存貨, mongodb叢集就不會挂掉。

shard,這就是傳說中的分片了。上面提到一個機器就算能力再大也有天花闆,就像軍隊打仗一樣,一個人再厲害喝血瓶也拼不過對方的一個師。俗話說三個臭皮匠頂個諸葛亮,這個時候團隊的力量就凸顯出來了。在網際網路也是這樣,一台普通的機器做不了的多台機器來做,如下圖:

一台機器的一個資料表 Collection1 存儲了 1T 資料,壓力太大了!在分給4個機器後,每個機器都是256G,則分攤了集中在一台機器的壓力。也許有人問一台機器硬碟加大一點不就可以了,為什麼要分給四台機器呢?不要光想到存儲空間,實際運作的資料庫還有硬碟的讀寫、網絡的IO、CPU和記憶體的瓶頸。在mongodb叢集隻要設定好了分片規則,通過mongos操作資料庫就能自動把對應的資料操作請求轉發到對應的分片機器上。在生産環境中分片的片鍵可要好好設定,這個影響到了怎麼把資料均勻分到多個分片機器上,不要出現其中一台機器分了1T,其他機器沒有分到的情況,這樣還不如不分片!

replica set,上兩節已經詳細講過了這個東東,怎麼這裡又來湊熱鬧!其實上圖4個分片如果沒有 replica set 是個不完整架構,假設其中的一個分片挂掉那四分之一的資料就丢失了,是以在高可用性的分片架構還需要對于每一個分片建構 replica set 副本集保證分片的可靠性。生産環境通常是 2個副本 + 1個仲裁。

說了這麼多,還是來實戰一下如何搭建高可用的mongodb叢集:

首先确定各個元件的數量,mongos 3個, config server 3個,資料分3片 shard server 3個,每個shard 有一個副本一個仲裁也就是 3 * 2 = 6 個,總共需要部署15個執行個體。這些執行個體可以部署在獨立機器也可以部署在一台機器,我們這裡測試資源有限,隻準備了 3台機器,在同一台機器隻要端口不同就可以,看一下實體部署圖:

下面是安裝配置

1,準備三台機器

ip: <code>10.19</code><code>.</code><code>21.241</code> ,<code>10.19</code><code>.</code><code>21.242</code> ,<code>10.19</code><code>.</code><code>21.243</code>

分别在每台機器上,同步時間伺服器

<code>yum install ntpdate -y</code>

<code>/usr/sbin/ntpdate cn.pool.ntp.org</code>

順便把硬體時間也同步下

<code></code>

<code>hwclock --systohc</code>

<code>10.19</code><code>.</code><code>21.241</code> <code>| success | rc=</code><code>0</code> <code>&gt;&gt;</code>

<code>10.19</code><code>.</code><code>21.243</code> <code>| success | rc=</code><code>0</code> <code>&gt;&gt;</code>

<code>10.19</code><code>.</code><code>21.242</code> <code>| success | rc=</code><code>0</code> <code>&gt;&gt;</code>

2,在一台機器上,下載下傳mongodb

<code>wget https:</code><code>//fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.8.tgz</code>

3,解壓安裝mongodb

<code>tar zxvf mongodb-linux-x86_64-rhel70-</code><code>3.2</code><code>.</code><code>8</code><code>.tgz</code>

<code>mv mongodb-linux-x86_64-rhel70-</code><code>3.2</code><code>.</code><code>8</code> <code>/usr/local/mongodb</code>

 4,在一台機器上,建立mongos config shard1 shard2 shard3五個目錄,因為mongos不存儲資料,隻需建立日志檔案目錄

建立mongos目錄和日志目錄

<code>mkdir -p /usr/local/mongodb/mongos/log</code>

建立config server資料目錄

<code>mkdir -p /usr/local/mongodb/config/data</code>

建立config server日志目錄

<code>mkdir -p /usr/local/mongodb/config/log</code>

建立shard1資料目錄和日志目錄

<code>mkdir -p /usr/local/mongodb/shard1/data /usr/local/mongodb/shard1/log</code>

建立shard2資料目錄和日志目錄

<code>mkdir -p /usr/local/mongodb/shard2/data /usr/local/mongodb/shard2/log</code>

建立shard3資料目錄和日志目錄

5,規劃5個元件對應的端口号,由于一個機器需要同時部署mongos, config server, shard1, shard2, shard3,是以需要用端口号進行區分

這個端口号可以自己定義,mongos:20000,config server:21000, shard1:22001, shard2:22002, shard3:22003

6,配置伺服器的配置檔案

<code>cat /usr/local/mongodb/config/mongod-configsvr.conf</code>

<code>dbpath=/usr/local/mongodb/config/data</code>

<code>port=</code><code>21000</code>

<code>logpath=/usr/local/mongodb/config/log/config.log</code>

<code>fork=</code><code>true</code>

<code>configsvr=</code><code>true</code>

<code>logappend=</code><code>true</code>

配置每台mongos伺服器

<code>cat /usr/local/mongodb/config/mongod-mongos.conf</code>

<code>configdb=</code><code>10.19</code><code>.</code><code>21.241</code><code>:</code><code>21000</code><code>,</code><code>10.19</code><code>.</code><code>21.242</code><code>:</code><code>21000</code><code>,</code><code>10.19</code><code>.</code><code>21.243</code><code>:</code><code>21000</code>

<code>port=</code><code>20000</code>

<code>logpath=/usr/local/mongodb/mongos/log/mongos.log</code>

配置各個分片的副本集

<code>cat /usr/local/mongodb/config/mongod-shardsvr1.conf</code>

<code>shardsvr=</code><code>true</code>

<code>replSet=shard1</code>

<code>port=</code><code>22001</code>

<code>dbpath=/usr/local/mongodb/shard1/data</code>

<code>logpath=/usr/local/mongodb/shard1/log/shard1.log</code>

<code>  </code> 

<code>cat /usr/local/mongodb/config/mongod-shardsvr2.conf</code>

<code>replSet=shard2</code>

<code>port=</code><code>22002</code>

<code>dbpath=/usr/local/mongodb/shard2/data</code>

<code>logpath=/usr/local/mongodb/shard2/log/shard2.log</code>

<code>cat /usr/local/mongodb/config/mongod-shardsvr3.conf</code>

<code>replSet=shard3</code>

<code>port=</code><code>22003</code>

<code>dbpath=/usr/local/mongodb/shard3/data</code>

<code>logpath=/usr/local/mongodb/shard3/log/shard3.log</code>

7,打包mongodb目錄,拷貝到另外兩台伺服器

<code>tar zcvf /mnt/mongodb.tar.gz /usr/local/mongodb</code>

<code>scp mongodb.tar.gz root</code><code>@10</code><code>.19.</code><code>21.242</code><code>:/mnt/</code>

<code>scp mongodb.tar.gz root</code><code>@10</code><code>.19.</code><code>21.243</code><code>:/mnt/</code>

被拷貝的兩台伺服器分别解壓

<code>tar zxvf /mnt/mongodb.tar.gz -C /</code>

 8,分别在每台機器上,啟動服務,三台機器必須先全部啟動mongod-configsvr.conf

<code>ln -s /usr/local/mongodb/bin/mongo* /usr/bin/mongod</code>

<code>mongod -f /usr/local/mongodb/config/mongod-configsvr.conf</code>

<code>mongos -f /usr/local/mongodb/config/mongod-mongos.conf  (上面指令全部執行完再運作,否則報錯)</code>

啟動各個分片的副本集

<code>mongod -f /usr/local/mongodb/config/mongod-shardsvr1.conf</code>

<code>mongod -f /usr/local/mongodb/config/mongod-shardsvr2.conf</code>

<code>mongod -f /usr/local/mongodb/config</code><code>//mongod-shardsvr3.conf</code>

9,登陸任意一台,連接配接mongodb

設定第一個分片副本集

<code>[root</code><code>@VM</code><code>-</code><code>241</code> <code>~]# mongo </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>22001</code>

<code>MongoDB shell version: </code><code>3.2</code><code>.</code><code>8</code>

<code>connecting to: </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>22001</code><code>/test</code>

使用admin資料庫

<code>mongos&gt; use admin</code>

<code>switched to db admin</code>

定義副本集配置

<code>mongos&gt; config={_id:</code><code>"shard1"</code><code>,members:[{_id:</code><code>0</code><code>,host:</code><code>"10.19.21.241:22001"</code><code>},{_id:</code><code>1</code><code>,host:</code><code>"10.19.21.242:22001"</code><code>},{_id:</code><code>2</code><code>,host:</code><code>"10.19.21.243:22001"</code><code>,arbiterOnly:</code><code>true</code><code>}]}</code>

<code>#####################################</code>

<code>{</code>

<code>"_id"</code> <code>: </code><code>"shard1"</code><code>,</code>

<code>"members"</code> <code>: [</code>

<code>"_id"</code> <code>: </code><code>0</code><code>,</code>

<code>"host"</code> <code>: </code><code>"10.19.21.241:22001"</code>

<code>},</code>

<code>"_id"</code> <code>: </code><code>1</code><code>,</code>

<code>"host"</code> <code>: </code><code>"10.19.21.242:22001"</code>

<code>"_id"</code> <code>: </code><code>2</code><code>,</code>

<code>"host"</code> <code>: </code><code>"10.19.21.243:22001"</code><code>,</code>

<code>"arbiterOnly"</code> <code>: </code><code>true</code>

<code>}</code>

<code>]</code>

初始化副本集配置

   &gt; rs.initiate(config);

<code>"info"</code> <code>: </code><code>"Config now saved locally.  Should come online in about a minute."</code><code>,</code>

<code>"ok"</code> <code>: </code><code>1</code>

設定第二個分片副本集

<code>[root</code><code>@VM</code><code>-</code><code>241</code> <code>~]# mongo </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>22002</code>

<code>connecting to: </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>22002</code><code>/test</code>

<code>&gt; use admin</code>

<code>&gt; config={_id:</code><code>"shard2"</code><code>,members:[{_id:</code><code>0</code><code>,host:</code><code>"10.19.21.241:22002"</code><code>},{_id:</code><code>1</code><code>,host:</code><code>"10.19.21.242:22002"</code><code>},{_id:</code><code>2</code><code>,host:</code><code>"10.19.21.243:22002"</code><code>,arbiterOnly:</code><code>true</code><code>}]}</code>

<code> </code> 

<code>初始化副本集配置</code>

<code>&gt; rs.initiate(config);</code>

設定第三個分片副本集

<code>[root</code><code>@VM</code><code>-</code><code>241</code> <code>~]# mongo </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>22003</code>

<code>connecting to: </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>22003</code><code>/test</code>

<code>&gt; config={_id:</code><code>"shard3"</code><code>,members:[{_id:</code><code>0</code><code>,host:</code><code>"10.19.21.241:22003"</code><code>},{_id:</code><code>1</code><code>,host:</code><code>"10.19.21.242:22003"</code><code>},{_id:</code><code>2</code><code>,host:</code><code>"10.19.21.243:22003"</code><code>,arbiterOnly:</code><code>true</code><code>}]}</code>

10,配置分片

目前搭建的mongodb配置伺服器,路由伺服器,各個分片伺服器,不過應用程式連接配接到mongs路由伺服器并不能使用分片機制,還需要在程式裡設定分片配置,讓分片生效。

連接配接mongos

<code>[root</code><code>@VM</code><code>-</code><code>241</code> <code>~]# mongo </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>20000</code>

<code>connecting to: </code><code>127.0</code><code>.</code><code>0.1</code><code>:</code><code>20000</code><code>/test</code>

串聯路由伺服器與配置設定副本集1

<code>mongos&gt; db.runCommand({addshard:</code><code>"shard1/10.19.21.241:22001,10.19.21.242:22001,10.19.21.243:22001"</code><code>});</code>

<code>{ </code><code>"shardAdded"</code> <code>: </code><code>"shard1"</code><code>, </code><code>"ok"</code> <code>: </code><code>1</code> <code>}</code>

#如裡shard是單台伺服器,用 db.runCommand( { addshard : “[: ]” } )這樣的指令加入,如果shard是副本集,用db.runCommand( { addshard : “replicaSetName/[:port][,serverhostname2[:port],…]” });這樣的格式表示 

串聯路由伺服器與配置設定副本集2

<code>mongos&gt; db.runCommand({addshard:</code><code>"shard2/10.19.21.241:22002,10.19.21.242:22002,10.19.21.243:22002"</code><code>});</code>

<code>{ </code><code>"shardAdded"</code> <code>: </code><code>"shard2"</code><code>, </code><code>"ok"</code> <code>: </code><code>1</code> <code>}</code>

串聯路由伺服器與配置設定副本集3

<code>mongos&gt; db.runCommand({addshard:</code><code>"shard3/10.19.21.241:22003,10.19.21.242:22003,10.19.21.243:22003"</code><code>});</code>

<code>{ </code><code>"shardAdded"</code> <code>: </code><code>"shard3"</code><code>, </code><code>"ok"</code> <code>: </code><code>1</code> <code>}</code>

檢視分片伺服器配置

<code>mongos&gt; db.runCommand({listshards:</code><code>1</code><code>})</code>

<code>"shards"</code> <code>: [</code>

<code>"host"</code> <code>: </code><code>"shard1/10.19.21.241:22001,10.19.21.242:22001"</code>

<code>"_id"</code> <code>: </code><code>"shard2"</code><code>,</code>

<code>"host"</code> <code>: </code><code>"shard2/10.19.21.241:22002,10.19.21.242:22002"</code>

<code>"_id"</code> <code>: </code><code>"shard3"</code><code>,</code>

<code>"host"</code> <code>: </code><code>"shard3/10.19.21.241:22003,10.19.21.242:22003"</code>

<code>],</code>

由于10.19.21.243是每個分片副本集的仲裁節點,是以上面沒有列出

11,目前配置服務、路由服務、分片服務、副本集服務都已經串聯起來了,但我們的目的是希望插入資料,資料能夠自動分片,連接配接在mongos上,準備讓指定的資料庫、指定的集合分片生效

指定資料庫裡面的索引

使用table1中的id字段的hash作為索引來分片,需要進入資料庫中去建立

<code>db.table1.ensureIndex({id:</code><code>"hashed"</code><code>});</code>

<code>db.table1.ensureIndex({id:</code><code>1</code><code>},{unique:</code><code>true</code><code>});</code>

指定資料庫testdb使分片生效,在admin庫中執行以下指令

<code>mongos&gt; db.runCommand({enablesharding:</code><code>"testdb"</code><code>});</code>

<code>{ </code><code>"ok"</code> <code>: </code><code>1</code> <code>}</code>

<code>或是</code>

<code>mongos&gt; sh.enableSharding(</code><code>'testdb'</code><code>);</code>

指定資料庫裡需要分片的集合和片鍵

<code>mongos&gt; db.runCommand({shardcollection:</code><code>"testdb.table1"</code><code>,key:{id:</code><code>"hashed"</code><code>}})</code>

<code>{ </code><code>"collectionsharded"</code> <code>: </code><code>"testdb.table1"</code><code>, </code><code>"ok"</code> <code>: </code><code>1</code> <code>}</code>

<code>mongos&gt; sh.shardCollection(</code><code>'testdb.table1'</code><code>,{id:</code><code>'hashed'</code><code>})</code>

我們設定testdb的 table1 表需要分片,根據 id 自動分片到 shard1 ,shard2,shard3 上面去。要這樣設定是因為不是所有mongodb 的資料庫和表 都需要分片!

<code>mongos&gt; use testdb</code>

<code>switched to db testdb</code>

插入測試資料

<code>for</code> <code>(var i=</code><code>1</code><code>;i&lt;=</code><code>100000</code><code>;i++)db.table1.save({id:i,</code><code>"test1"</code><code>:</code><code>"testvar1"</code><code>});</code>

<code>WriteResult({ </code><code>"nInserted"</code> <code>: </code><code>1</code> <code>})</code>

檢視分片情況如下:

<code>mongos&gt; db.table1.stats();</code>

<code>"sharded"</code> <code>: </code><code>true</code><code>,</code>

<code>"capped"</code> <code>: </code><code>false</code><code>,</code>

<code>"ns"</code> <code>: </code><code>"testdb.table1"</code><code>,</code>

<code>"count"</code> <code>: </code><code>100000</code><code>,</code>

<code>"size"</code> <code>: </code><code>5400000</code><code>,</code>

<code>"storageSize"</code> <code>: </code><code>1822720</code><code>,</code>

<code>"totalIndexSize"</code> <code>: </code><code>3674112</code><code>,</code>

<code>"indexSizes"</code> <code>: {</code>

<code>"_id_"</code> <code>: </code><code>991232</code><code>,</code>

<code>"id_hashed"</code> <code>: </code><code>2682880</code>

<code>"avgObjSize"</code> <code>: </code><code>54</code><code>,</code>

<code>"nindexes"</code> <code>: </code><code>2</code><code>,</code>

<code>"nchunks"</code> <code>: </code><code>6</code><code>,</code>

<code>"shards"</code> <code>: {</code>

<code>"shard1"</code> <code>: {</code>

<code>"count"</code> <code>: </code><code>33755</code><code>,</code>

<code>"size"</code> <code>: </code><code>1822770</code><code>,</code>

<code>"storageSize"</code> <code>: </code><code>614400</code><code>,</code>

<code>"wiredTiger"</code> <code>: {</code>

<code>"metadata"</code> <code>: {</code>

<code>"formatVersion"</code> <code>: </code><code>1</code>

<code>......</code>

<code>"totalIndexSize"</code> <code>: </code><code>1224704</code><code>,</code>

<code>"_id_"</code> <code>: </code><code>335872</code><code>,</code>

<code>"id_hashed"</code> <code>: </code><code>888832</code>

<code>"shard2"</code> <code>: {</code>

<code>"count"</code> <code>: </code><code>33143</code><code>,</code>

<code>"size"</code> <code>: </code><code>1789722</code><code>,</code>

<code>"storageSize"</code> <code>: </code><code>606208</code><code>,</code>

<code>"totalIndexSize"</code> <code>: </code><code>1196032</code><code>,</code>

<code>"_id_"</code> <code>: </code><code>327680</code><code>,</code>

<code>"id_hashed"</code> <code>: </code><code>868352</code>

<code>"shard3"</code> <code>: {</code>

<code>"count"</code> <code>: </code><code>33102</code><code>,</code>

<code>"size"</code> <code>: </code><code>1787508</code><code>,</code>

<code>"storageSize"</code> <code>: </code><code>602112</code><code>,</code>

<code>"totalIndexSize"</code> <code>: </code><code>1253376</code><code>,</code>

<code>"id_hashed"</code> <code>: </code><code>925696</code>

可以看到資料分到3個分片,shard1:33755 shard2:33143 shard3:33102

----------------------------------------------------------------------------------------------

java程式調用分片叢集,因為我們配置了三個mongos作為入口,就算其中哪個入口挂掉了都沒關系,使用叢集用戶端程式如下:

<code>public</code> <code>class</code> <code>TestMongoDBShards {</code>

<code>       </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args) {</code>

<code>             </code><code>try</code> <code>{</code>

<code>                  </code><code>List&lt;ServerAddress&gt; addresses = </code><code>new</code> <code>ArrayList&lt;ServerAddress&gt;();</code>

<code>                  </code><code>ServerAddress address1 = </code><code>new</code> <code>ServerAddress(</code><code>"10.19.21.241"</code> <code>, </code><code>20000</code><code>);</code>

<code>                  </code><code>ServerAddress address2 = </code><code>new</code> <code>ServerAddress(</code><code>"10.19.21.242"</code> <code>, </code><code>20000</code><code>);</code>

<code>                  </code><code>ServerAddress address3 = </code><code>new</code> <code>ServerAddress(</code><code>"10.19.21.243"</code> <code>, </code><code>20000</code><code>);</code>

<code>                  </code><code>addresses.add(address1);</code>

<code>                  </code><code>addresses.add(address2);</code>

<code>                  </code><code>addresses.add(address3);</code>

<code>                  </code><code>MongoClient client = </code><code>new</code> <code>MongoClient(addresses);</code>

<code>                  </code><code>DB db = client.getDB( </code><code>"testdb"</code> <code>);</code>

<code>                  </code><code>DBCollection coll = db.getCollection( </code><code>"table1"</code> <code>);</code>

<code>                  </code><code>BasicDBObject object = </code><code>new</code> <code>BasicDBObject();</code>

<code>                  </code><code>object.append( </code><code>"id"</code> <code>, </code><code>1</code><code>);</code>

<code>                  </code><code>DBObject dbObject = coll.findOne(object);</code>

<code>                  </code><code>System. out .println(dbObject);</code>

<code>            </code><code>} </code><code>catch</code> <code>(Exception e) {</code>

<code>                  </code><code>e.printStackTrace();</code>

<code>            </code><code>}</code>

<code>      </code><code>}</code>

整個分片叢集搭建完了,思考一下我們這個架構是不是足夠好呢?其實還有很多地方需要優化,比如我們把所有的仲裁節點放在一台機器,其餘兩台機器承擔了全部讀寫操作,但是作為仲裁的192.168.0.138相當空閑。讓機器3 192.168.0.138多分擔點責任吧!架構可以這樣調整,把機器的負載分的更加均衡一點,每個機器既可以作為主節點、副本節點、仲裁節點,這樣壓力就會均衡很多了,如圖:

當然生産環境的資料遠遠大于目前的測試資料,大規模資料應用情況下我們不可能把全部的節點像這樣部署,硬體瓶頸是硬傷,隻能擴充機器。要用好mongodb還有很多機制需要調整,不過通過這個東東我們可以快速實作高可用性、高擴充性,是以它還是一個非常不錯的Nosql元件。

再看看我們使用的mongodb java 驅動用戶端 MongoClient(addresses),這個可以傳入多個mongos 的位址作為mongodb叢集的入口,并且可以實作自動故障轉移,但是負載均衡做的好不好呢?打開源代碼檢視:

<a href="http://s3.51cto.com/wyfs02/M00/86/9B/wKiom1fFK2KDiWHnAAAXWv5WbtE284.png" target="_blank"></a>

它的機制是選擇一個ping 最快的機器來作為所有請求的入口,如果這台機器挂掉會使用下一台機器。那這樣。。。。肯定是不行的!萬一出現雙十一這樣的情況所有請求集中發送到這一台機器,這台機器很有可能挂掉。一但挂掉了,按照它的機制會轉移請求到下台機器,但是這個壓力總量還是沒有減少啊!下一台還是可能崩潰,是以這個架構還有漏洞!不過這個文章已經太長了,後續解決吧。

參考:http://blog.jobbole.com/72643/

本文轉自奔跑在路上部落格51CTO部落格,原文連結http://blog.51cto.com/qiangsh/1844023如需轉載請自行聯系原作者

qianghong000