最近由于要存储大规模结构化数据,想到了MongoDB的口号For giant ideas,于是假设了下图架构的一个mongoDB集群。
先说说选型的原因,结构化数据很多数据库都可以存储,最常用的是mysql,而且mysql的集群也屡见不鲜。比如mycat或者mysqlproxy这种数据库网关就可以放置在多个普通的mysql服务器前面,或者像腾讯退出的TDSQL这种商业版本也是有内置数据库网关的,通过数据库网关解析SQL语句,然后把不同的INSERT语句分拆,分别放到不同的数据库中。而且mysql数据库原生可以通过binlog做某一个分片的复制集,但是mysql数据库缺点也有很多,比如mongoDB可以存储松散的结构化数据,其属性可以随时修改,但是mysql集群中要添加表的一列或修改表结构其成本和风险是巨大的。第二,MongoDB的这一整套路由分发和复制集都是mongoDB原生组件完成的,如mongos组件发挥的就是数据库路由器的功能,而该组件是mongodb官方开发和维护,其适配性要比采用第三方的数据网关要好一些。
除了选型之外,其他的数据分割的逻辑与mysql集群大同小异,都需要选择片键然后根据片键去分割数据,并确定数据落在哪一个分片上。
我上面建立的这个集群一共使用了8台物理服务器。最上面三台物理服务器中,每台物理服务器里放一个config(mongod)进程,和一个mongos进程。三个config节点组成config复制集,这样任意一个config挂掉都不会对整体造成影响。三个mongos采用相同的配置,在连接mongoDB集群的时候,将URL写成
mongodb://username:password@192.168.1.1:2000,192.168.1.2:2000,192.168.1.3:2000/DatabaseName
这种模式,由客户端自动的在3个mongos中选择一个连接,并在一个mongos出故障时由客户端自动迁移到另一个mongos上去。这样就不怕某个mongos突然挂掉。
下面的操作使用的MongoDB版本为4.0.6
然后是中间三台物理服务器每个里面都运行着一个mongod进程,用来存放真实的业务数据,这三个服务器的mongod均设置为Master,并且分属不同的分片,加载不同内容的配置文件。
然后我们就有了3个分片了,然后我们再为每个分片设置复制集,组成一个3x3的集群,即3个分片,每个分片里有3个数据副本,防止数据丢失。
于是在同一个机房或者同城机房内在找一台算力和存储都比Master大一些的两台物理机,每台物理机里执行三个mongod进程,分别数据分片1,分片2和分片3的Slave。这样三分片三复制集的集群就搭建完成了。下面是详细步骤
搭建Config节点复制集
config节点有一个就够用了,但是为了实现高可用,我这里使用3台物理机跑三个config节点,并组成复制集。
config节点的配置文件如下
sharding:
clusterRole: configsvr
replication:
replSetName: confset
net:
port: 7017
bindIp: 0.0.0.0
systemLog:
destination: file
logAppend: true
path: /mnt/mongo/conf/mongod.log
storage:
dbPath: /mnt/mongo/conf
journal:
enabled: true
processManagement:
fork: true # fork and run in background
pidFilePath: /mnt/mongo/conf/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
跑mongod进程很方便,只需编写好一个简短的配置文件就可以了,这也是mongodb比mysql方便的地方,即配置文件结构非常简单,不需要考虑太多。
其中要注意,clusterRole必须填configsvr,这一点与普通的mongod数据库进程不一样。因为config节点虽然也可以当做普通的mongo数据来使用,但是其最主要的作用不是存储业务数据,而是与mongos进程配合,存储每个分片节点的信息,数据分片规则,和分片后每个chunk的存储信息。所以不应该在config节点中存储任何业务数据。
replSetName可以自己随便起,但在三个config节点中应该保持相同,这样才能把三个config节点添加到同一个复制集中去
port就是开放的端口,注意和其他的进程不冲突就可以了,我这里三台config节点的配置文件都是一样的,用的一样的数据库端口。
systemLog就是配置mongo运行时产生log日志的存放位置,storage里的dbPath就是存放数据库数据文件的位置,如果目录不存在需要手工创建。
在这里要提醒一下,默认搭建出来的mongo数据库集群是没有管理员密码的,连接也不需要提供用户名和密码,非常不安全。所以我们这里先使用mongodb集群密码验证的方式生成相关的密钥。
生成密钥使用openssl命令即可,如果数据库服务器本身没有openssl命令,可以在其他设备上生成后拷贝过来
openssl rand -base64 741 > /etc/mongo/mongodb-keyfile
生成的密钥大概是下面这个样子,懒得生成的同学可以直接把我下面这个拷贝过去使用
bJd/FkxJaYfZPL5bbP7eRI2sh8EydhuZa8jXUtzlT+uYz0oKHKhnMBECsX+CZfRG
xebslFdXrWdAuhwVvSoFDGtp9o7O9kwJbna0txKxhFfeYcDh5X81hQT7TbflY1oH
JVgCFMrfejz9vR5bMa5ieumhDJ0WruvO3y1fvOVZN4/SDkWahxY88mF40GTambGw
q6VeIV4aEPOrqDUu7TqTzuaCGZBRd6EQoWGqQ/bsmq8Q37hag8Pdk1dFE0jyUvsA
ol00lIFN+49OkTcO/t20/MUae+opcIn8sUtV7a80WyiklH9AxIRR6Xjl/Peb+vbg
gsyq2XK3LFqga/WWDY16AYGBBGn53oCxjkmDH+HZ5VL2IlAoEELUIYHKpSiafUCg
/fsVloVJh7