MongoDB庖丁解牛(Sharding Cluster)

  • A+
所属分类:MongoDB

什么是分片

高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。

MongoDB分片是使用多个服务器存储数据的方法,以支持巨大的数据存储和对数据进行操作。分片技术可以满足MongoDB数据量大量增长的需求,当一台MongoDB服务器不足以存储海量数据或者不足以提供可接受的读写吞吐量时,我们就可以通过在多台服务器上分割数据,使得数据库系统能存储和处理更多的数据。

MongoDB分片优势

分片为应对高吞吐量与大数据量提够了方法

使用分片减少了每个分片需要处理的请求数,因此,通过水平扩展,群集可以提高自己的存储容量。比如,当插入一条数据时,应用只需要访问存储这条数据的分片。

使用分片减少了每个分片村存储的数据

分片的优势在于提供类似线性增长的架构,提高数据可用性,提高大型数据库查询服务器的性能。当MongoDB单点数据库服务器存储成为瓶颈、单点数据库服务器的性能成为瓶颈或需要部署大型应用以充分利用内存时,可以使用分片技术。

MongoDB分片群集的组成

Shard:分片服务器,用于存储实际的数据块,实际生产环境中一个shard server 角色可以由几台服务器组成一个Peplica Set 承担,防止主机单点故障。

Config Server:配置服务器,存储了整个分片群集的配置信息,其中包括chunk信息。

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

部署MongoDB分片群集

群集部署的搭建思路,利用三台服务器,分别安装mongodb数据库,每台服务器创建五个实例(mongos、configs、shard1、shard2、shard3)。三台不同的服务器上的相同名称的实例,创建为一个复制集,分别包括主节点,副节点,仲裁节点。mongos不需创建复制集,config不需指定主副节点及仲裁节点,但是要创建复制集。三台服务器的操作步骤略有差别,但是大多是都是重复操作,步骤完全一致。

集群部署(环境规划)

node01:192.168.20.101 node02:192.168.20.102 node03:192.168.20.103
mongos(27017) mongos(27017) mongos(27017)
config(30000) config(30000) config(30000)
shard1主节点(40001) shard1副节点(40001) shard1仲裁节点(40001)
shard2仲裁节点(40002) shard2主节点(40002) shard2副节点(40002)
shard1副节点(40003) shard1仲裁节点(40003) shard1主节点(40003)

CentOS Linux release 7.6.1810 (Core) 

禁止selinux以及防火墙

setenforce 0
systemctl stop firewalld
systemctl disable firewalld

配置ntp时间同步

*/5 * * * * /usr/sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1

将系统时区改为上海时间(即CST时区)

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

配置网络

[root@k8s-node01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=b0bd91ab-08ef-46bb-b8d7-d83990ff3327
DEVICE=ens33
ONBOOT=yes
IPADDR0=192.168.20.101
PREFIXO0=24
GATEWAY0=192.168.20.2
DNS1=192.168.20.2
DNS2=8.8.8.8

分别修改主机名

hostnamectl set-hostname node01
hostnamectl set-hostname node02
hostnamectl set-hostname node03
cat /etc/hostname
ping baidu.com

SSH免认证

Master执行一路回车

[root@k8s-master tools]# ssh-keygen

node节点分发密钥

cd /root/.ssh/
ssh-copy-id root@192.168.20.102
ssh-copy-id root@192.168.20.103

master hosts绑定node主机名

vim /etc/hosts
192.168.20.101 node01
192.168.20.102 node02
192.168.20.103 node03

安装支持软件和mongodb

yum install openssl-devel -y
mkdir /root/tools && cd /root/tools
tar zxf mongodb-linux-x86_64-4.0.6.tgz -C /usr/local
mv /usr/local/mongodb-linux-x86_64-4.0.6 /usr/local/mongodb
ll /usr/local/mongodb

创建数据存储目录和日志存储目录

路由服务器不存储数据,因此就不需要创建数据存储目录,只需创建config、shard1、shaed2、shard3即可,日志文件创建完成之后还需要给予权限。

mkdir -p /data/mongodb/logs/
mkdir /etc/mongodb/
mkdir /data/mongodb/config/
mkdir /data/mongodb/shard{1,2,3}
touch /data/mongodb/logs/shard{1,2,3}.log
touch /data/mongodb/logs/mongos.log
touch /data/mongodb/logs/config.log
chmod 777 /data/mongodb/logs/*.log

创建管理用户,修改目录权限

useradd -M -u 8000 -s /sbin/nologin mongo
chown -R mongo.mongo /usr/local/mongodb
chown -R mongo.mongo /data/mongodb

设置环境变量

echo "PATH=/usr/local/mongodb/bin:$PATH" >> /etc/profile
source /etc/profile

系统内存优化( *注意*这些优化都是临时的,重启失效)

ulimit -n 25000
ulimit -u 25000
echo 0 > /proc/sys/vm/zone_reclaim_mode 
sysctl -w vm.zone_reclaim_mode=0
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

部署config服务器

[root@node01 .ssh]# vim /etc/mongodb/config.conf 
pidfilepath = /data/mongodb/logs/config.pid           
dbpath = /data/mongodb/config/                        
logpath = /data/mongodb/logs/config.log               
logappend = true
bind_ip = 0.0.0.0                                     #监听地址
port = 30000                                          
fork = true
replSet=configs                                       #复制集名称
configsvr = true
maxConns=20000                                        #最大连接数

将配置文件发送到其他服务器

scp /etc/mongodb/config.conf root@node02:/etc/mongodb/
scp /etc/mongodb/config.conf root@node03:/etc/mongodb/

启动config实例(三台服务器操作一致)

mongod -f /etc/mongodb/config.conf  
ps -ef|grep mongo

配置复制集(任一台操作即可),这里在node01操作,建议三台服务器都进入数据库,方便查看角色变更

进入mongo

mongo --port 30000

创建复制集

config={_id:"configs",members:[{_id:0,host:"192.168.20.101:30000"},{_id:1,host:"192.168.20.102:30000"},{_id:2,host:"192.168.20.103:30000"}]}

初始化复制集

rs.initiate(config)

查看副本集状态

rs.status()

主副本查询

db.isMaster()

部署shard1分片服务器

node01创建配置文件

[root@node01 .ssh]# vim /etc/mongodb/shard1.conf
pidfilepath = /data/mongodb/logs/shard1.pid
dbpath = /data/mongodb/shard1/
logpath = /data/mongodb/logs/shard1.log
logappend = true
journal = true
quiet = true
bind_ip = 0.0.0.0
port = 40001
fork = true
replSet=shard1
shardsvr = true
maxConns=20000

将文件发送到其他服务器

scp /etc/mongodb/shard1.conf root@node02:/etc/mongodb/
scp /etc/mongodb/shard1.conf root@node03:/etc/mongodb/

启动shard1实例(三台服务器操作一致)

mongod -f /etc/mongodb/shard1.conf  
ps -ef|grep shard1

配置shard1分片服务器

在shard分片服务器的创建中,需要注意的点是,不是在任一台服务器上创建都能成功的,如果选择在预先设置为仲裁节点的服务器上创建复制集会报错。以shard1分片服务器为例,可以在node01和node02服务器上创建复制集,在node03上创建则会失败,因为在复制集创建之前,node3已经被设置为仲裁节点。

node3创建失败报错如下:

This node, 192.168.20.103:40001, with _id 2 is not electable under the new configuration version 1 for replica set shard1"

三台服务器都进入数据库,方便查看角色变更

mongo --port 40001
use admin
config={_id:"shard1",members:[{_id:0,host:"192.168.20.101:40001",priority:2},{_id:1,host:"192.168.20.102:40001",priority:1},{_id:2,host:"192.168.20.103:40001",arbiterOnly:true}]}

初始化副本集

rs.initiate(config)

查看副本集状态(可以看到node1是PRIMARY,node2的状态是SECONDARY,node3是ARBITER)

rs.status()

部署shard2分片服务器

node01创建配置文件

[root@node01 ~]# vim /etc/mongodb/shard2.conf
pidfilepath = /data/mongodb/logs/shard2.pid
dbpath = /data/mongodb/shard2/
logpath = /data/mongodb/logs/shard2.log
logappend = true
journal = true
quiet = true
bind_ip = 0.0.0.0
port = 40002
fork = true
replSet=shard2
shardsvr = true
maxConns=20000

将配置文件发送到其他服务器(三台服务器操作一致)

scp /etc/mongodb/shard2.conf root@node02:/etc/mongodb/
scp /etc/mongodb/shard2.conf root@node03:/etc/mongodb/

启动shard2实例

mongod -f /etc/mongodb/shard2.conf
ps -ef|grep shard2

配置shard2复制集(非仲裁节点服务器node2)三台服务器都进入数据库,方便查看角色变更

mongo --port 40002
use admin
config={_id:"shard2",members:[{_id:0,host:"192.168.20.101:40002",arbiterOnly:true},{_id:1,host:"192.168.20.102:40002",priority:2},{_id:2,host:"192.168.20.103:40002",priority:1}]}

初始化副本集

rs.initiate(config)

查看副本集状态(可以看到node1是ARBITER,node2的状态是PRIMARY,node3是SECONDARY)

rs.status()

部署shard3分片服务器

node01创建配置文件

[root@node01 ~]# vim /etc/mongodb/shard3.conf
pidfilepath = /data/mongodb/logs/shard3.pid
dbpath = /data/mongodb/shard3/
logpath = /data/mongodb/logs/shard3.log
logappend = true
journal = true
quiet = true
bind_ip = 0.0.0.0
port = 40003
fork = true
replSet=shard3
shardsvr = true
maxConns=20000

将配置文件发送到其他服务器

scp /etc/mongodb/shard3.conf root@node02:/etc/mongodb/
scp /etc/mongodb/shard3.conf root@node03:/etc/mongodb/

启动shard3实例(三台服务器操作一致)

mongod -f /etc/mongodb/shard3.conf
ps -ef|grep shard3

配置shard复制集(非仲裁节点服务器node01)

建议三台服务器都进入数据库,方便查看角色变更

mongo --port 40003
use admin
config={_id:"shard3",members:[{_id:0,host:"192.168.20.101:40003",priority:1},{_id:1,host:"192.168.20.102:40003",arbiterOnly:true},{_id:2,host:"192.168.20.103:40003",priority:2}]}

初始化副本集

rs.initiate(config);

查看副本集状态(可以看到node1是SECONDARY,node2的状态是ARBITER,node3是PRIMARY)

rs.status()

部署路由服务器

node01创建配置文件

[root@node01 ~]# vim /etc/mongodb/mongos.conf
pidfilepath = /data/mongodb/logs/mongos.pid
logpath=/data/mongodb/logs/mongos.log
logappend = true
bind_ip = 0.0.0.0
port = 27017
fork = true
configdb = configs/192.168.20.101:30000,192.168.20.102:30000,192.168.20.103:30000
maxConns=20000

将配置文件发送到其他服务器

scp /etc/mongodb/mongos.conf root@node02:/etc/mongodb/
scp /etc/mongodb/mongos.conf root@node03:/etc/mongodb/

启动mongos实例(三台服务器操作一致*注意*这里是“mongos”而非“mongod”)

mongos -f /etc/mongodb/mongos.conf
ps -ef|grep mongos

启用分片功能

进入mongo路由服务器,因为默认端口即是27017,所以此处不接端口号

mongo
mongos> use admin

此处先添加shard1和shard2分片服务器,shard3待会添加

mongos> sh.addShard("shard1/192.168.20.101:40001,192.168.20.102:40001,192.168.20.103:40001")
mongos> sh.addShard("shard2/192.168.20.101:40002,192.168.20.102:40002,192.168.20.103:40002")

查看群集状态

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
  	"_id" : 1,
  	"minCompatibleVersion" : 5,
  	"currentVersion" : 6,
  	"clusterId" : ObjectId("5c6be1e2ccae0aebef2ac7c5")
  }
  shards:
        {  "_id" : "shard1",  "host" : "shard1/192.168.20.101:40001,192.168.20.102:40001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/192.168.20.102:40002,192.168.20.103:40002",  "state" : 1 }
  active mongoses:
        "4.0.6" : 3
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }

测试服务器分片功能

设置分片chunk大小

mongo
mongos> use config
switched to db config

设置块大小为1M是方便实验,不然就需要插入海量数据

mongos> db.settings.save({"_id":"chunksize","value":1})
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize" })

模拟写入数据

mongo
mongos> use python
switched to db python
mongos> show collections

在python库的user表中循环写入五万条数据

mongos> for(i=1;i<=50000;i++){db.user.insert({"id":i,"name":"jack"+i})}
WriteResult({ "nInserted" : 1 })

启用数据库分片

数据库分片就有针对性,可以自定义需要分片的库或者表,毕竟也不是所有数据都是需要分片操作的

mongos>sh.enableSharding("python")

为表创建的索引

创建索引的规则是不能一致性太高,要具有唯一性,例如序号,比如性别这一类重复性太高的就不适合做索引,以”id“为索引

mongos> db.user.createIndex({"id":1})

启用表分片

mongos> sh.shardCollection("python.user",{"id":1})

查看分片情况

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
  	"_id" : 1,
  	"minCompatibleVersion" : 5,
  	"currentVersion" : 6,
  	"clusterId" : ObjectId("5c6be1e2ccae0aebef2ac7c5")
  }
  shards:
        {  "_id" : "shard1",  "host" : "shard1/192.168.20.101:40001,192.168.20.102:40001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/192.168.20.102:40002,192.168.20.103:40002",  "state" : 1 }
  active mongoses:
        "4.0.6" : 3
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  yes
        Collections with active migrations: 
                python.user started at Tue Feb 19 2019 23:58:08 GMT+0800 (CST)
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                1 : Success
  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) 
        {  "_id" : "python",  "primary" : "shard2",  "partitioned" : true,  "version" : {  "uuid" : UUID("ab823c3f-0b23-49da-a2e6-9e0af01fdd61"),  "lastMod" : 1 } }
                python.user
                        shard key: { "id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard1	1
                                shard2	5
                        { "id" : { "$minKey" : 1 } } -->> { "id" : 9893 } on : shard1 Timestamp(2, 0) 
                        { "id" : 9893 } -->> { "id" : 19786 } on : shard2 Timestamp(2, 1) 
                        { "id" : 19786 } -->> { "id" : 29679 } on : shard2 Timestamp(1, 2) 
                        { "id" : 29679 } -->> { "id" : 39572 } on : shard2 Timestamp(1, 3) 
                        { "id" : 39572 } -->> { "id" : 49465 } on : shard2 Timestamp(1, 4) 
                        { "id" : 49465 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(1, 5)

node03手动添加分片服务器,查看分片情况是否发生变化

mongos> use admin
switched to db admin
mongos> sh.addShard3("192.168.20.101:40003,192.168.20.102:40003,192.168.20.103:40003")
mongos> sh.status()

服务器又对数据进行重新分片,当你再次移除一个分片服务器,此时又会对数据再次进行分片处理,MongoDB对数据的处理非常灵活

查看node运行的进程

[root@node03 ~]# ps -ef|grep mongo
root       7138      1  1 Feb19 ?        00:04:01 mongod -f /etc/mongodb/config.conf
root       7259      1  0 Feb19 ?        00:02:10 mongod -f /etc/mongodb/shard1.conf
root      10055      1  1 Feb19 ?        00:02:45 mongod -f /etc/mongodb/shard2.conf
root      10638      1  1 Feb19 ?        00:00:16 mongod -f /etc/mongodb/shard3.conf
root      10741      1  0 Feb19 ?        00:00:04 mongos -f /etc/mongodb/mongos.conf

参考原文

http://blog.51cto.com/13643643/2148825

https://www.cnblogs.com/myblog1314/p/3940180.html

http://blog.51cto.com/kaliarch/2047358

YaLei

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: