OpenStack Ceilometer -- 后台数据存储优化之MongoDB的分片存储设置

时间:2021-02-08 04:59:39

https://xiaofandh12.github.io/Mongo-Shard

关于MongoDB

MongoDB中的概念与关系型数据库之间的对应:

  • Database --> Database
  • Collection --> Table
  • Document --> Row

MongoDB相较于关系型数据库的优势:

  • 简化关系型数据库复杂的关联问题
  • 摆脱关系模型里面的强一致性限制
  • MongoDB可以做到水平扩展和高可用

学习MongoDB有几个比较重要的方面:

  • CRUD操作
  • 聚合(Aggregation)操作
  • 索引(Indexs)
  • 存储引擎(Storage)
  • 复制集(Replication)
  • 分片(Sharding)
  • 各种命令

MongoDB的部署

  • yum info mongo-10gen查看yum源中是否包含MongoDB的相关资源。

  • vi /etc/yum.repos.d/10gen.repo添加yum源,若已有则不添加。

    1. [10gen]
    2. name=10gen Repository
    3. baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64
    4. gpgcheck=0
  • yum info mongo-10gen-server,配置好yum源之后,查看yum源中是否包含MongoDB的服务器包的信息。

  • 安装MongoDB的服务器端和客户端工具:

    1. yum install mongo-10gen-server
    2. yum install mongo-10gen
  • 根据需要修改/etc/mongod.conf,启动MongoDB: service mongod start

MongoDB的简单操作

连接MongoDB

  • 相关操作如下:

    1. [root@node-51 ~]# mongo --host hostIP/hostName --port portNum
    2. mongos> show dbs
    3. admin *GB
    4. ceilometer *GB
    5. config *GB
    6. mongos> use ceilometer
    7. mongos> show collections
    8. meter
    9. project
    10. resource
    11. system.indexes
    12. system.users
    13. user

查询meter中所有的数据

  • 相关操作如下:

    1. mongos> db.meter.find()
    2. mongos> db.meter.find().count()

查询meter中所有的counter_name

  • 相关操作如下:

    1. mongos> db.meter.distinct("counter_name")

查询meter中各counter_name有多少条记录

  • 相关操作如下:

    1. mongos> db.meter.aggregate([
    2. {
    3. $group: {
    4. _id: "$counter_name",
    5. count: {$sum:1}
    6. }
    7. },
    8. { $match: { count: { $gt: 1 } } }
    9. ])

我们一般对SQL型的数据库比较熟,因此对一些复杂的查询我们可以用SQL的思维来思考,再到页面SQL to Aggregation Mapping Chart中去寻找对应的MongoDB的查询方式

查询counter_name为hardware.memory.total时,resource_id分别为什么

  • 相关操作如下:

    1. mongos> db.meter.aggregate([
    2. {
    3. $match: {
    4. counter_name: "hardware.memory.total"
    5. }
    6. },
    7. {
    8. $group: {
    9. _id: {
    10. counter_name: "$counter_name",
    11. resource_id: "$resource_id"
    12. }
    13. }
    14. }
    15. ])

分片与复制集(Sharding与Replication)

一个完整的数据库可以备份为多份,原始的数据库和备份的数据库就组成了一个复制集,由此可以提高容错性。

一个完整的数据库的数据可以进行分片,通过分片可以把数据库中的完整数据分为多份分别存储在多台机器中,由此可以提高吞吐量。

分片和复制集是分开的两个功能,可以只做分片,也可以只做复制集。

如果既有分片又有复制集的话,那么同一个分片组成的集合就是一个复制集,如一个数据库分为两片shard1、shard2,可以再分别对shard1、shard2做两个复制shard1_1、shard1_2、shard2_1、shard2_2,那么shard1、shar1_1、shard1_2组成一个复制集,shard2、shard2_1、shard2_2组成另一个复制集。

MongoDB的每一个分片或复制集中的分片都可以不存储在同一个机器上,只要指定好IP地址和端口号即可。

本文并不讨论复制集的问题。

MongoDB的分片,分为两片,两个分片在同一台物理机上

OpenStack Ceilometer -- 后台数据存储优化之MongoDB的分片存储设置

node-51为一台物理机,它的IP地址为172.31.2.51。

图中各服务所在IP和端口号,对应过来如下:

  • shard1 --> 172.31.2.51:20000
  • shard2 --> 172.31.2.51:20001
  • config --> 172.31.2.51:30000
  • mongos --> 172.31.2.51:27017

client通过mongos(172.31.2.51:27017)即可对数据库进行读写。

  1. 新建数据目录和日志目录

    1. [root@node-51 ~]# mkdir -p /data/shard/s0
    2. [root@node-51 ~]# mkdir -p /data/shard/s1
    3. [root@node-51 ~]# mkdir -p /data/shard/log
  2. 配置shard server

    1. [root@node-51 ~]# /usr/bin/mongod --shardsvr --port 20000 --dbpath /data/shard/s0 --fork --logpath /data/shard/log/s0.log --directoryperdb
    2. [root@node-51 ~]# /usr/bin/mongod --shardsvr --port 20001 --dbpath /data/shard/s1 --fork --logpath /data/shard/log/s1.log --directoryperdb
  3. 配置config server和route server

    1. [root@node-51 ~]# mkdir -p /data/shard/config
    2. [root@node-51 ~]# /usr/bin/mongod --configsvr --port 30000 --dbpath /data/shard/config --fork --logpath /data/shard/log/config.log --directoryperdb
    3. [root@node-51 ~]# /usr/bin/mongos --port 27017 --configdb 172.31.2.51:30000 --fork --logpath /data/shard/log/route.log --chunkSize 1
  4. admin数据库和ceilometer数据库配置

    1. [root@node-51 ~]# mongo admin --host 172.31.2.51 --port 27017
    2. mongos> use admin
    3. mongos> db.runCommand({addshard:'172.31.2.51:20000'})
    4. mongos> db.runCommand({addshard:'172.31.2.51:20001'})
    5. mongos> db.runCommand({enablesharding:'ceilometer'})
    6. mongos> db.runCommand({shardcollecton:'ceilometer.meter',key:{counter_name:1}})
    7. mongos> use ceilometer
    8. mongos> db.addUser("ceilometer","ceilometer")
    9. mongos> db.meter.stats()

    在这里ceilometer是一个新建的数据库,OpenStack模块的openstack-ceilometer需要连接MongoDB中的ceilometer数据库,而openstack-ceilomter在连接MongoDB中的ceilometer数据库时,使用的是用户名:ceilometer,密码:ceilometer来连接的(再安装openstack-ceilometer时设置的),所以有了db.addUser("ceilometer","ceilomter")。

  5. 修改ceilometer.conf,并重启ceilometer服务

    将ceilometer.conf中的connection改为如下:

    1. connection=mongodb://ceilometer:ceilometer@172.31.2.51:27017/ceilometer

    重启ceilometer服务:

    1. [root@node-51 ~]# service openstack-ceilometer-alarm-evalutor restart
    2. [root@node-51 ~]# service openstack-ceilometer-alarm-notifier restart
    3. [root@node-51 ~]# service openstack-ceilometer-api restart
    4. [root@node-51 ~]# service openstack-ceilometer-central restart
    5. [root@node-51 ~]# service openstack-ceilometer-collector restart

Mongodb分片后的开机启动设置

现在有一个问题是,设置好分片重启机器后,又得重新执行分片的命令。目前解决的办法是在/etc/rc.d/rc.local/中新增命令。

  • 关闭mongod开机启动:

    1. [root@node-51 ~]# chkconfig --list | grep mongod --> 可以查出mongod在哪几个运行级别上运行了
    2. [root@node-51 ~]# chkconfig --levels 2345 mongod off
  • 在文件/etc/rc.d/rc.local中,增加下述内容:

    1. /usr/bin/mongod --shardsvr --port 20000 --dbpath /data/shard/s0 --fork --logpath /data/shard/log/s0.log --directoryperdb
    2. /usr/bin/mongod --shardsvr --port 20001 --dbpath /data/shard/s1 --fork --logpath /data/shard/log/s1.log --directoryperdb
    3. /usr/bin/mongod --configsvr --port 30000 --dbpath /data/shard/config --fork --logpath /data/shard/log/config.log --directoryperdb
    4. /usr/bin/mongos --port 27017 --configdb 172.31.2.51:30000 --fork --logpath /data/shard/log/route.log --chunkSize 1
    5. service openstack-ceilometer-alarm-evalutor restart
    6. service openstack-ceilometer-alarm-notifier restart
    7. service openstack-ceilometer-api restart
    8. service openstack-ceilometer-central restart
    9. service openstack-ceilometer-collector restart

这个问题没算完全解决,有空再看看《鸟哥的linux私房菜》第18章 认识系统服务(daemons)和第20章 启动流程、模块管理与Loader。

MongoDB的分片,分为三片,三个分片在不同的物理机上

这小节我会介绍一下把MongoDB中的数据库分为三片,并且把三个分片存储在不同物理机上的方法。

OpenStack Ceilometer -- 后台数据存储优化之MongoDB的分片存储设置

mongos1,mongos2,mongos3代表三台物理机,它们的IP地址为:

  • mongos1 --> 172.31.2.135
  • mongos2 --> 172.31.2.136
  • mongos3 --> 172.31.2.137

图中各服务所在IP和端口号,对应过来如下:

  • shard1 --> 172.31.2.135:27018
  • shard2 --> 172.31.2.136:27018
  • shard3 --> 172.31.2.137:27018
  • config1 --> 172.31.2.135:27019
  • mongos1 --> 172.31.2.135:27017

client通过连接mongos1(172.31.2.135:27017)即可对数据库进行读写。

下面详细介绍一下整个过程:

  1. 安装好操作系统,安装好MongoDB,重要提醒:关闭iptables,seLinux(因为这个我中午都没睡成午觉...)

    1. service iptables stop
    2. setenforce 0
  2. 在mongos1, mongos2, mongos3中新建目录

    1. [root@mongos1 ~]# mkdir -p /data/shard/s1
    2. [root@mongos1 ~]# mkdir -p /data/shard/log
    3. [root@mongos1 ~]# mkdir -p /data/shard/config
    4. [root@mongos2 ~]# mkdir -p /data/shard/s2
    5. [root@mongos2 ~]# mkdir -p /data/shard/log
    6. [root@mongos3 ~]# mkdir -p /data/shard/s3
    7. [root@mongos3 ~]# mkdir -p /data/shard/log
  3. 在mongos1, mongos2, mongos3中配置shard server

    1. [root@mongos1 ~]# mongod --shardsvr --port 27018 --dbpath /data/shard/s1 --fork --logpath /data/shard/log/s1.log --directoryperdb
    2. [root@mongos2 ~]# mongod --shardsvr --port 27018 --dbpath /data/shard/s2 --fork --logpath /data/shard/log/s2.log --directoryperdb
    3. [root@mongos3 ~]# mongod --shardsvr --port 27018 --dbpath /data/shard/s3 --fork --logpath /data/shard/log/s3.log --directoryperdb
  4. 在mongos1中配置config server

    1. [root@mongos1 ~]# mongod --configsvr --port 27019 --dbpath /data/shard/config --fork --logpath /data/shard/log/config.log --directoryperdb
  5. 在mongos1中配置route server

    1. [root@mongos1 ~]# mongos --port 27017 --configdb 172.31.2.135:27019 --fork --logpath /data/shard/log/route.log --chunkSize 1
  6. 在mongos1中配置admin数据库和ceilometer数据库

    1. [root@mongos1 ~]# mongo admin --host 172.31.2.135 --port 27017
    2. mongos> db.runCommand({addshard:'172.31.2.135:27018'})
    3. mongos> db.runCommand({addshard:'172.31.2.136:27018'})
    4. mongos> db.runCommand({addshard:'172.31.2.137:27018'})
    5. mongos> db.runCommand({enablesharding:'ceilometer'})
    6. mongos> db.runCommand({shardCollection:'ceilometer.meter',key:{counter_name:1}})
    7. mongos> use ceilometer
    8. mongos> db.addUser("ceilometer", "ceilometer")
    9. mongos> db.meter.stats()
    10. mongos> sh.status()
  7. 修改ceilometer.conf,并重启ceilometer服务

    将ceilometer.conf中的connection改为如下:

    1. connection=mongodb://ceilometer:ceilometer@172.31.2.135:27017/ceilometer

    重启ceilometer服务:

    1. [root@node-51 ~]# service openstack-ceilometer-alarm-evalutor restart
    2. [root@node-51 ~]# service openstack-ceilometer-alarm-notifier restart
    3. [root@node-51 ~]# service openstack-ceilometer-api restart
    4. [root@node-51 ~]# service openstack-ceilometer-central restart
    5. [root@node-51 ~]# service openstack-ceilometer-collector restart

    可以再到mongos1中去查看数据量db.meter.find().count(),每隔一段时间执行一次,数字是不是越来越大。

MongoDB:Expire Data from Collections by Setting TTL

当MongoDB数据库中的数据量变得很大时,查询的速度也会随之下降,定期的删除或转存数据库中的数据就成为了一个很重要的需求了。

在MongoDB 2.2中就引进了一个功能,即Expire Data from Collections by Setting TTL,有了这个功能我们只要做一个简单的设置就可以定期的删除历史数据了。

在Ceilometer的配置文件中,设置了ttl的相关参数后,Ceiloemter的后台数据库就会去自动清理数据库中的历史数据,而后台数据库不论是MongoDB还是关系型数据库都可以,当后台是MongoDB时就正是利用了MongoDB 2.2中引入的Expire Data from Collections by Setting TTL这项功能。

Ceilometer中新增自动清理数据库中的历史数据的blueprint页面为:Database data TTL,review页面为:Database data TTL Review