MongoDB 分片

    当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。

    • 本地磁盘不够大
    • 当请求量巨大时会出现内存不足。
    • 垂直扩展价格昂贵(内存、磁盘、cpu)

    MongoDB分片

    下图展示了在MongoDB中使用分片集群结构分布:

    MongoDB 分片 - 图1

    上图中主要有如下所述三个主要组件:

    • Shard:

      用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组或者一个relica set承担,防止主机单点故障

    • 路由表服务。每一台都具有全部chunk的路由信息。

    • Query Routers:

      前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

    分片结构端口分布如下:

    步骤一:启动Shard Server

    1. sudo mkdir -p /MongoDB/shard/s1 /MongoDB/shard/s2 /MongoDB/shard/log
    2. sudo mongod --port 27031 --dbpath=/MongoDB/shard/s1
    3. sudo mongod --port 27032 --dbpath=/MongoDB/shard/s2

    步骤二: 启动Config Server

    1. sudo rm -rf /MongoDB/shard/config
    2. sudo mkdir -p /MongoDB/shard/config
    3. sudo mongod --port 27100 --dbpath=/MongoDB/shard/config

    注意:这里我们完全可以像启动普通mongodb服务一样启动,不需要添加—shardsvr和configsvr参数。因为这两个参数的作用就是改变启动端口的,所以我们自行指定了端口就可以。

    步骤三: 启动Route Process

    1. mongos --port 27777 --configdb 192.168.17.129:27100

    步骤四: 配置Sharding

    接下来,我们使用MongoDB Shell登录到mongos,添加Shard节点

    步骤五:对某个数据库test启用分片

    1. mongos> db.runCommand({ enablesharding:"test" }) #设置分片存储的数据库
    2. { "ok" : 1 }

    步骤六:对collection进行分片

    1. mongos> db.runCommand({ shardcollection: "test.mycol", key: { _id:1}})
    2. { "collectionsharded" : "test.mycol", "ok" : 1 }

    步骤五:测试

    1. mongo test --port 27777

    输出10000条数据

    程序代码内无需太大更改,直接按照连接普通的mongo数据库那样,将数据库连接接入接口27777

    步骤六: 查看分片情况

    查看分片情况时,必须在config(配置服务器上执行)而且必须在admin(如mongo 127.0.0.1:27100/admin)集合下执行

    输出如下:

    1. -- Sharding Status ---
    2. sharding version: {
    3. "_id" : 1,
    4. "minCompatibleVersion" : 5,
    5. "clusterId" : ObjectId("57cfcdfef06b33543fdeb52e")
    6. }
    7. shards:
    8. { "_id" : "shard0000", "host" : "localhost:27031" }
    9. { "_id" : "shard0001", "host" : "localhost:27032" }
    10. active mongoses:
    11. "3.2.7" : 1
    12. balancer:
    13. Currently enabled: yes
    14. Currently running: no
    15. Failed balancer rounds in last 5 attempts: 0
    16. Migration Results for the last 24 hours:
    17. 1 : Success
    18. databases:
    19. test.mycol
    20. shard key: { "_id" : 1 }
    21. unique: false
    22. balancing: true
    23. chunks:
    24. shard0000 2
    25. shard0001 1
    26. { "_id" : { "$minKey" : 1 } } -->> { "_id" : 1 } on : shard0001 Timestamp(2, 0)
    27. { "_id" : 1 } -->> { "_id" : 57 } on : shard0000 Timestamp(2, 1)
    28. { "_id" : 57 } -->> { "_id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 3)
    1. mongo admin --port 27100 #config(配置服务器上执行)
    2. use config
    3. > db.chunks.find().pretty()
    4. {
    5. "_id" : "test.mycol-_id_MinKey",
    6. "lastmod" : Timestamp(2, 0),
    7. "lastmodEpoch" : ObjectId("57da5df2bb44f821e869eaeb"),
    8. "ns" : "test.mycol",
    9. "min" : {
    10. "_id" : { "$minKey" : 1 }
    11. },
    12. "max" : {
    13. "_id" : 1
    14. "shard" : "shard0001"
    15. }
    16. {
    17. "_id" : "test.mycol-_id_1.0",
    18. "lastmod" : Timestamp(2, 1),
    19. "lastmodEpoch" : ObjectId("57da5df2bb44f821e869eaeb"),
    20. "ns" : "test.mycol",
    21. "min" : {
    22. },
    23. "max" : {
    24. "_id" : 57
    25. },
    26. "shard" : "shard0000"
    27. }
    28. {
    29. "_id" : "test.mycol-_id_57.0",
    30. "lastmod" : Timestamp(1, 3),
    31. "lastmodEpoch" : ObjectId("57da5df2bb44f821e869eaeb"),
    32. "ns" : "test.mycol",
    33. "min" : {
    34. "_id" : 57
    35. },
    36. "max" : {
    37. "_id" : { "$maxKey" : 1 }
    38. },
    39. "shard" : "shard0000"
    40. }
    41. > db.settings.find()
    42. { "_id" : "chunksize", "value" : NumberLong(64) }

    我们可以看见刚开始的块分裂成了三块分别是(-∞,1)在shard0001上,[1,57][57,+∞)shard0000上。

    说明:这里需要说明的是MongoDB中的区间是左闭右开的。

    查看结果db.mycol.stats()

    1. mongo --port 27777
    2. use test
    3. switched to db test
    4. mongos> show collections
    5. mycol
    6. mycol111
    7. mycol2

    Hashed Sharding

    选择哈希片键最大的好处就是保证数据在各个节点分布基本均匀,下面使用_id作为哈希片键做个简单的测试:

    总结:哈希分片将提供的片键散列成一个非常大的长整型作为最终的片键。