304、Sharding分片环境部署(详述)

Sharding分片环境部署(详述)

前言:

Sharding是一种可以将数据分发到不同主机上的方法,主要是用于解决MongoDB巨大数据量和高吞吐量的问题。我们一开始使用单机,但是为了安全和一些读写分离改为副本集,但是业务增长快速的情况下,可能遇到很多性能上的问题;例如巨大的查询频率可能会耗尽所有CPU资源,高吞吐量可能使得I/O成为瓶颈。对于这些问题其实我们有两种方案:垂直扩展 和 水平扩展

  • 垂直扩展:说白了就是增加单台机器的资源,用更多CPU,更大内存,使用SSD硬盘;但是硬件技术上的局限性可能导致最后还是无法满足你的业务需求
  • 水平扩展:通过分离数据集和多服务器负载来实现,按需添加额外服务器可以更好的解决大数据量和大吞吐量的问题;
    而分片就是为了实现水平扩展而生的集群架构

架构

Sharding分片架构一般由3部分组成:

  • mongos server:路由节点,作为一个查询路由而存在,承接client端与分片服务器之前的数据传输(或者叫分发)
  • config server: 配置节点,存储集群的配置信息,以及各个分片数据的元数据信息,3.2以后必须以replica set形式部署(简称CSRS)
  • shard server:分片节点,实际存储数据的服务器,每个分片节点根据片键的选择只持有集合的一部分数据。
    官方架构图:
    image

部署架构:
config server:

  • 10.67.37.45:38001 (primary)
  • 10.67.37.46:38001 (secondary)
  • 10.67.37.47:38001 (secondary)

mongos server:

  • 10.67.37.45:37000
  • 10.67.37.46:37000
  • 10.67.37.47:37000

shard1:

  • 10.67.37.45:37001(primary)
  • 10.67.37.46:37001 (secondary)
  • 10.67.37.47:37001 (secondary)

shard2:

  • 10.67.37.45:37002 (secondary)
  • 10.67.37.46:37002 (primary)
  • 10.67.37.47:37002 (secondary)

shard3:

  • 10.67.37.45:37003 (secondary)
  • 10.67.37.46:37003 (secondary)
  • 10.67.37.47:37003 (primary)


    image

部署步骤:

信息:

  • OS: Redhat 7.6
  • MongoDB version: mongod 4.0
  • CPU: 8
  • RAM: 48G
    注:由于是测试环境,机器数量受限,所以上述15个节点服务均部署在3台服务器上,生产环境的话可以根据自己情况部署;
    另:因为本教程部署的是开启认证模式的cluster sharding架构,所以要求cluster中的所有成员必须使用一致的内部认证机制和设定;

1.部署配置服务节点config server复制集

1.1 创建相应目录

(在10.67.37.45上执行下述操作)

[mongo@wqdcsrv090 shard]$ cd /data/johnny/shard
[mongo@wqdcsrv091 shard]$ mkdir cfg                           --配置文件存放目录
[mongo@wqdcsrv090 shard]$ mkdir -p configsvr/dbdata/    --数据目录
[mongo@wqdcsrv090 shard]$ mkdir -p configsvr/logs/      --日志目录
[mongo@wqdcsrv090 shard]$ mkdir -p configsvr/keyfile/   --keyfile文件目录
[mongo@wqdcsrv090 shard]$ mkdir -p configsvr/pid/       --进程id存放目录
1.2 配置启动文件

编辑config server的配置文件/data/johnny/shard/cfg/config.cnf,内容如下
除了参数bindIp需要根据不同服务器IP地址修改,其他不变。

storage:
   dbPath: /data/johnny/shard/configsvr/dbdata
   journal:
      enabled: true
      commitIntervalMs: 50
   directoryPerDB: true
   engine: wiredTiger
   wiredTiger:
      engineConfig:
         directoryForIndexes: true
systemLog:
   quiet: false
   path: /data/johnny/shard/configsvr/logs/configsvr.log
   destination: file
   logAppend: true
   logRotate: rename
processManagement:
    fork: true
    pidFilePath: /data/johnny/shard/configsvr/pid/configsvr.pid
net:
   port: 38001
   maxIncomingConnections: 1000
   wireObjectCheck: true
   bindIp: localhost,10.67.37.45            #注意此参数需要根据不同的服务器IP进行修改
security:
   keyFile: /data/johnny/shard/configsvr/keyfile/security
replication:
   oplogSizeMB: 3072
   replSetName: configsvr
sharding:
   clusterRole: configsvr

注:如果不太清楚上述参数的意义,请参考官方文档启动参数说明

1.3 创建keyfile文件
[mongo@wqdcsrv090 keyfile]$ pwd
/data/johnny/shard/configsvr/keyfile
[mongo@wqdcsrv090 keyfile]$ openssl rand -base64 756 > security
[mongo@wqdcsrv090 keyfile]$ chmod 400 security
[mongo@wqdcsrv090 keyfile]$ ls -l
total 4
-r-------- 1 mongo mongo 1024 Sep 25 15:53 security

注:分片架构中所有的节点必须使用相同内容的security文件,3.6版本后文件权限注意是400,之前版本是600;

1.4 启动config server进程
[mongo@wqdcsrv090 shard]$ /apps/mongodb4.0/bin/mongod -f /data/johnny/shard/cfg/config.cnf
about to fork child process, waiting until server is ready for connections.
forked process: 5652
child process started successfully, parent exiting

出现上述信息表示启动成功。

1.5 部署其他config server

请根据上述1.1 ~ 1.4步骤部署其他两个config server的节点(10.67.37.46:38001, 10.67.37.47:38001),务必注意security文件就不需要重新创建了直接copy到其他服务器即可;

1.6 初始化config server复制集

待上述3个config server节点都启动成功后,进行复制集初始化操作,请使用localhost接口登录任意一台38001端口实例(因为已经开启了keyfile内部认证,所以在没有创建任何管理员用户之前只能通过localhost接口特性来登录)

[mongo@wqdcsrv090 shard]$ /apps/mongodb4.0/bin/mongo localhost:38001/admin
MongoDB shell version v4.0.10
connecting to: mongodb://localhost:38001/admin?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("6ed4375b-a95c-47e6-8a03-f0ae04328b31") }
MongoDB server version: 4.0.10
> rs.initiate(
   {
     _id: "configsvr",
     configsvr: true,
     members: [
       { _id : 0, host : "10.67.37.45:38001",priority:2 },
       { _id : 1, host : "10.67.37.46:38001" },
       { _id : 2, host : "10.67.37.47:38001" }
     ]
   }
 )
configsvr:PRIMARY>

待10秒钟之后,将会选举出primary节点,此时config server的复制集部署完毕,可以通过命令rs.status()查看集群状态

2.部署分片服务节点shard

部署分片shard1
(在10.67.37.45上执行下述操作)

2.1 创建shard1文件目录
[mongo@wqdcsrv090 shard]$ cd /data/johnny/shard
[mongo@wqdcsrv090 shard]$ mkdir -p shard1/dbdata
[mongo@wqdcsrv090 shard]$ mkdir -p shard1/logs
[mongo@wqdcsrv090 shard]$ mkdir -p shard1/keyfile
[mongo@wqdcsrv090 shard]$ mkdir -p shard1/pid
2.2 shard1配置文件

配置shard2,shard3时注意修改文件目录名称,以及端口号

storage:
   dbPath: /data/johnny/shard/shard1/dbdata
   journal:
      enabled: true
      commitIntervalMs: 50
   directoryPerDB: true
   engine: wiredTiger
   wiredTiger:
      engineConfig:
         cacheSizeGB: 2
         directoryForIndexes: true
systemLog:
   quiet: false
   path: /data/johnny/shard/shard1/logs/shard1.log
   destination: file
   logAppend: true
   logRotate: rename
processManagement:
    fork: true
    pidFilePath: /data/johnny/shard/shard1/pid/shard1.pid
net:
   port: 37001
   maxIncomingConnections: 1000
   wireObjectCheck: true
   bindIp: localhost,10.67.37.45
security:
   keyFile: /data/johnny/shard/shard1/keyfile/security
replication:
   oplogSizeMB: 3072
   replSetName: shard1
sharding:
   clusterRole: shardsvr
2.3 启动shard1的mongod进程
[mongo@wqdcsrv090 shard]$ /apps/mongodb4.0/bin/mongod -f /data/johnny/shard/cfg/shard1.cnf
2.4 启动分片shard1的其他节点:

请根据上述2.1 ~ 2.3步骤部署shard1分片的其他两个节点(10.67.37.46:37001, 10.67.37.47:37001),务必注意security文件就不需要重新创建了直接copy到其他服务器即可;

2.5 初始化分片shard1的复制集

待上述shard1分片的3个server节点都启动成功后,进行shard1分片复制集的初始化操作
登录10.67.37.45上的37001实例

[mongo@wqdcsrv090 shard]$ /apps/mongodb4.0/bin/mongo localhost:37001/admin
MongoDB shell version v4.0.10
connecting to: mongodb://localhost:37001/admin?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("3f0b2538-c52a-4a1c-a601-92c44fb7a902") }
MongoDB server version: 4.0.10
> rs.initiate(
...   {
...     _id: "shard1",
...     members: [
...       { _id : 0, host : "10.67.37.45:37001",priority:2 },
...       { _id : 1, host : "10.67.37.46:37001" },
...       { _id : 2, host : "10.67.37.47:37001" }
...     ]
...   }
... )
{ "ok" : 1 }
shard1:PRIMARY>

可以通过命令rs.status查看复制集各个成员状态, 这里我们使用priority:2将10.67.37.45:37001节点优先指定为primary角色;

2.6 创建分片shard1的本地管理员

登录到主节点的admin库,利用localhost exception特性即 使用mongo -h localhost37001 登录数据库:,创建第一个用户(此用户至少包含userAdminAnyDatabase权限),此用户是为了对于以后单独维护分片复制集而用,请不要使用此用户单独登录某个分片进行数据的DML操作;

shard1:PRIMARY> db.createUser({
user:"dba",
pwd:"admin123",
roles:[{role:"root",db:"admin"}]
})
2.7 部署其他分片shard2,shard3

请根据步骤2.1 ~ 2.6, 部署分片shard2,shard3,注意在部署时修改对应复制集名称、目录名称等。
对于其他两个分片复制集,建议根据如下初始化方案:
shard2:

rs.initiate(
   {
     _id: "shard2",
     members: [
       { _id : 0, host : "10.67.37.45:37002" },
       { _id : 1, host : "10.67.37.46:37002",priority:2 },
       { _id : 2, host : "10.67.37.47:37002" }
     ]
   }
 )

shard3:

rs.initiate(
   {
     _id: "shard3",
     members: [
       { _id : 0, host : "10.67.37.45:37003" },
       { _id : 1, host : "10.67.37.46:37003" },
       { _id : 2, host : "10.67.37.47:37003",priority:2 }
     ]
   }
 )
  • shard2: 10.67.37.46:37002(primary)
  • shard3: 10.67.37.47:37003(primary)
    注:不同分片初始化时,请注意修改_id的名称,否则会报错;

3. 部署路由服务节点mongos

3.1 创建目录

mongos服务都是单独运行的,不需要也不能配置成复制集形式,但是为了路由节点的高可用性,最好建立多个mongos节点
如下操作在10.67.37.45上操作

[mongo@wqdcsrv090 shard]$ cd /data/johnny/shard
[mongo@wqdcsrv090 shard]$ mkdir -p mongos/logs
[mongo@wqdcsrv090 shard]$ mkdir -p mongos/keyfile
[mongo@wqdcsrv090 shard]$ mkdir -p mongos/pid

注:因为mongos服务不需要存储数据,所以我们不需要创建dbdata数据目录

3.2 mongos路由服务的配置文件
systemLog:
   quiet: false
   path: /data/johnny/shard/mongos/logs/mongos.log
   destination: file
   logAppend: true
   logRotate: rename
processManagement:
    fork: true
    pidFilePath: /data/johnny/shard/mongos/pid/mongos.pid
net:
   port: 37000
   maxIncomingConnections: 3000
   wireObjectCheck: true
   bindIp: localhost,10.67.37.45
security:
   keyFile: /data/johnny/shard/mongos/keyfile/security
sharding:
   configDB: configsvr/10.67.37.45:38001,10.67.37.46:38001,10.67.37.47:38001

注:configDB参数这里填写的是config server复制集的信息,configsvr是复制集名称;
因为mongos不存放数据,所以不需要storage的相关参数。

3.3 启动mongos进程
[mongo@wqdcsrv090 cfg]$ /apps/mongodb4.0/bin/mongos -f /data/johnny/shard/cfg/mongos.cnf
about to fork child process, waiting until server is ready for connections.
forked process: 25980
child process started successfully, parent exiting

注:路由服务进程启动时,使用的是mongos程序,而不是mongod,这里一定要注意;如果这里无法启动,请注意观看log日志文件;

3.4 部署其他mongos节点

请使用步骤3.1 ~ 3.3在其他两个服务器(10.67.37.46,10.67.37.47)上部署mongos进程,以提供路由的HA高可用;

3.5 创建cluster集群的管理员账号

注意,这次创建的管理员与上面创建的分片local账号dba不一样,下面要创建的账号是会存放到config server上,而并非在各个分片上;此账号是用来管理整个cluster集群的。

[mongo@wqdcsrv090 cfg]$ /apps/mongodb4.0/bin/mongo localhost:37000/admin
MongoDB shell version v4.0.10
connecting to: mongodb://localhost:37000/admin?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("2182380b-d614-42a0-8f9f-b1f760f2cc1e") }
MongoDB server version: 4.0.10
mongos> db.createUser({
... user:"root",
... pwd:"admin123",
... roles:[{role:"root",db:"admin"}]
... })
mongos>

4. 添加分片

虽然上述我们部署好了shard1,shard2,shard3的复制集架构,但是其实并没有加入到cluster集群中,我们需要通过mongos将各个分片节点加入到集群中;使用刚才创建的集群管理账号root,登录到mongos的实例(37000端口)

[mongo@wqdcsrv090 cfg]$ /apps/mongodb4.0/bin/mongo localhost:37000/admin -uroot -padmin123
MongoDB shell version v4.0.10
connecting to: mongodb://localhost:37000/admin?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("a2d6d30d-c0e3-4d18-be1f-22bdd9f118a6") }
MongoDB server version: 4.0.10
mongos> sh.addShard("shard1/10.67.37.45:37001,10.67.37.46:37001,10.67.37.47:37001")         //添加分片shard1
{
        "shardAdded" : "shard1",
        "ok" : 1,           //表示添加分片成功
        "operationTime" : Timestamp(1569479300, 8),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1569479300, 8),
                "signature" : {
                        "hash" : BinData(0,"soCeJXEgzeQlO8J7nJjGM3CjGcM="),
                        "keyId" : NumberLong("6740522498976120853")
                }
        }
}
mongos> sh.addShard("shard2/10.67.37.45:37002,10.67.37.46:37002,10.67.37.47:37002")             //添加分片shard2
mongos> sh.addShard("shard3/10.67.37.45:37003,10.67.37.46:37003,10.67.37.47:37003")             //添加分片shard3

当你完成添加分片后可以通过命令sh.status()查看集群状态

mongos> sh.status()
--- Sharding Status ---
  sharding version: {       //cluster配置的基本信息
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,       //当前config server的版本
        "clusterId" : ObjectId("5d8b2580cb888b1fa65f6ad6")  //整个cluster集群的一个标识符id
  }
  shards:   //当前各个分片的成员,state:1表示此分片可以被识别,否则为0
        {  "_id" : "shard1",  "host" : "shard1/10.67.37.45:37001,10.67.37.46:37001,10.67.37.47:37001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/10.67.37.45:37002,10.67.37.46:37002,10.67.37.47:37002",  "state" : 1 }
        {  "_id" : "shard3",  "host" : "shard3/10.67.37.45:37003,10.67.37.46:37003,10.67.37.47:37003",  "state" : 1 }
  active mongoses:
        "4.0.10" : 3        //表示当前活跃的mongos数量(最近60秒内ping的结果)
  autosplit:    //自动分裂是否开启
        Currently enabled: yes
  balancer:     //平衡器相关状态信息
        Currently enabled:  yes         //是否开启
        Currently running:  no          //当前是否在运行
        Failed balancer rounds in last 5 attempts:  0       //最近5分钟chunk迁移失败的次数
        Migration Results for the last 24 hours:            //最近24小时的迁移结果信息
                No recent migrations
  databases:    //当前启动分片的库信息
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard1  1
                        { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : shard1 Timestamp(1, 0)

5. 如何对表进行分片

上述所有操作都完成,我们的分片架构就算是部署完成了,但是如果想要使用上分片特性,我们需要对某个表进行开启分片的动作;

mongos> sh.enableSharding("testdb")         //需要首先对库进行分片功能启动
mongos> sh.shardCollection("testdb.t1",{age:1})     //对库下的某个表进行分片,片键选择是age:1,代表的是范围分片

当你对testdb.t1表进行insert操作时,会根据age值而被路由插入到不同的分片节点上,可以使用如下脚本简单循环插入一批数据

mongos> for(var i=2;i<100000;i++){var a = Math.floor((Math.random()*100)+1);db.t1.insert({_id:i,age:a,name:"johnny"});}

注:因为分片架构是以chunk为一个单元进行迁移的,默认chunkSize是64M,也就是说只有一个chunk块达到64M后才会进行分裂,而当不同分片间的chunk数量差达到2以上时才会引起balancer进行自动迁移;

参考官网地址:
Deploy a Sharding
Deploy a Sharding with Access Control

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 拓扑结构介绍:(两个分片的分片集群) 共采用3台虚拟机进行模拟,采用的是一机多实例的模式 hosts文件: 192...
    深度遗忘阅读 743评论 0 0
  • 高可用性即HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计...
    小波同学阅读 21,010评论 6 53
  • 来自公众号:马哥Linux运维作者:赵峰峰 mongodb是最常用的nosql数据库,在数据库排名中已经上升到了前...
    码农小光阅读 472评论 0 2
  • Mongodb分片概括 分片在多台服务器上分布数据的方法, Mongodb使用分片来支持具有非常大的数据集和高吞吐...
    Vernon阅读 539评论 0 1
  • 一、环境说明: 1、操作系统:CentOS Linux release 7.4.1708 2、mongodb版本:...
    张伟科阅读 983评论 0 1