MongoDB复制集简介

Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,提供数据的高可用。

YMODEM是用的什么CRC_mongo

MongoDB C Driver

mongoc 是官方的mongo驱动,用于通过程序来控制mongo数据库。

目前所有MongoDB复制集的配置都是通过mongo客户端进行配置的,无法实现自动配置。
#传统的老方法,需要手动配置,无法自动化配置
mongo --port=28017
use admin
config = {_id: 'my_repl', members: [
                          {_id: 0, host: '10.0.0.134:28017'},
                          {_id: 1, host: '10.0.0.134:28018'},
                          {_id: 2, host: '10.0.0.134:28019'}]
          }
rs.initiate(config)
use test;
db.movies.insert([ { "title" : "Jaws", "year" : 1975, "imdb_rating" : 8.1 },{ "title" : "Batman", "year" : 1989, "imdb_rating" : 7.6 },
] );

现在新解决方法是通过编写后台程序MongoControlServer通过mongoc向mongo数据发送创建配置复制集命令。

YMODEM是用的什么CRC_replSet_02

MongoC编写Command接口

//头文件
class mongodb_api
{
public:
	static mongodb_api& instance();
	/*MongoDB数据库初始化*/
	int mongodb_init(const char* url);
	/*清理数据库*/
	int mongodb_cleanup();
	int mongodb_do_command(const char* databasename, std::string command,std::string& replys);
private:
	mongodb_api();
	static mongodb_api* s_instance;
	void* m_mongodb_ptr=nullptr;
};
class  mango_db
{
public:
	int mongodb_init(const char* url);
	
	int create_client_pool();
	
	int destory_client_pool();
	//mongodb有一系列的自有的命令,包括管理类命令、地理信息命令等
	int  do_command(const char*databasename, const bson_t *command, bson_t &reply);
private:
	int m_ulthreads = 10;
	void *  m_pool=nullptr;
	void *  m_url = nullptr;
	std::string  m_strurl;
};
//mongoc的接口用于与mongo通信
#include <mongoc.h>
mongodb_api* mongodb_api::s_instance = nullptr;
mongodb_api& mongodb_api::instance()
{
	if (s_instance == nullptr)
	{
		s_instance = new mongodb_api;
	}
	return *s_instance;
}

int mango_db::mongodb_init(const char* url)
{
	int ulret = 0;
	m_strurl = url;
	mongoc_init();
	return ulret;
}
int mongodb_api::mongodb_cleanup()
{
	int ulret = 0;
	mango_db* dbapi = static_cast<h3c_cloud_mango_db*>(m_mongodb_ptr);
	if (dbapi == nullptr){ return ulret;}
	dbapi->destory_client_pool();
}
	
int mango_db::create_client_pool()
{
	int ulret = 0;
	mongoc_client_pool_t * client_pool=nullptr;
	mongoc_uri_t         *uri=nullptr;
	uri = mongoc_uri_new(m_strurl.c_str());//url指定ip地址,没有指定
	client_pool = mongoc_client_pool_new(uri);
	m_pool = static_cast<void*>(client_pool);
	m_url = static_cast<void*>(uri);
	return ulret;
}

int mango_db::destory_client_pool()
{
	int ulret = ERROR_COMMON_SUCCEED;
	if (m_url == nullptr || m_pool == nullptr)
	{
		return 1;
	}
	mongoc_client_pool_destroy(static_cast<mongoc_client_pool_t*>(m_pool));
	mongoc_uri_destroy(static_cast<mongoc_uri_t*>(m_url));
	mongoc_cleanup();
	return ulret;
}

int mongodb_api::mongodb_do_command(const char* databasename, std::string command, std::string& replys)
{
	int ulret = 0;
	mango_db* dbapi = static_cast<mango_db*>(m_mongodb_ptr);
	if (dbapi == nullptr){ return ERROR_COMMON_FALT; }
	bson_error_t errorinfo;
	bson_t reply;
	bson_t* cond = bson_new_from_json((const unsigned char*)command.c_str(), command.length(), &errorinfo);
	ulret = dbapi->do_command(databasename, cond, reply);
	char *condStr = bson_as_json(&reply, NULL);
	replys = condStr;
	bson_free(condStr);
	bson_destroy(&reply);
	return ulret;
}

int mango_db::do_command(const char*databasename,const bson_t *command, bson_t &reply)
{
	int ulret = 0;
	mongoc_client_pool_t *pool = static_cast<mongoc_client_pool_t*>(m_pool);
	mongoc_client_t      *client;
	bson_error_t error;
	client = mongoc_client_pool_pop(pool);//从连接池中获取连接对象 
	if (client == nullptr){
		H3C_CLOUD_MONGODB_LOG1(H3C_LOG_ERROR, "fail get client ptr url:[%s] database name:[%s]", databasename);
		return 1;
	}
	//删除指定的行
	if (!mongoc_client_command_simple(client, databasename, command, NULL, &reply, &error))
	{
		char *commandStr = bson_as_json(command, NULL);
		H3C_CLOUD_MONGODB_LOG4(H3C_LOG_ERROR, "fail do command url:[%s] database name:[%s]  command [%s] error [%s]", m_strurl.c_str(), databasename, commandStr, error.message);
		bson_free(commandStr);
		mongoc_client_pool_push(pool, client);
		return 1;
	}
	mongoc_client_pool_push(pool, client);
	return 0;
}

通过MongoC编写复制集的配置

以下是编写的测试代码,用于添加复制集节点。生产环境下可以编写一个后台程序自动检测mongo后台服务,自己检查mongo ip 自动生成

**"{“replSetInitiate”:{"_id":“COOL”,“members”:[{"_id":0,“host”:“10.90.15.198:27017”},{"_id":1,“host”:“10.90.15.199:27017”},{"_id":2,“arbiterOnly”:true,“host”:“10.90.15.200:27017”}]}}"**; 配置文件,可以实现mongo数据库的自动更新,创建复制集(replSet)
//通过mongoc进行复制集配置(例子)
ULONG_32 h3c_cloud_manager_db::h3c_cloud_command()
{
	ULONG_32 ulret = ERROR_COMMON_SUCCEED;
	//检查复制集
	std::string command = "{\"replSetGetStatus\":1}";
	std::string reply;
	ulret = h3c_cloud_mongodb_api::instance().mongodb_do_command("admin", command,reply);
	if (ulret != ERROR_COMMON_SUCCEED){
		H3C_CLOUD_MAN_LOG2(H3C_LOG_ERROR, "fail create json  info [%s] [%s]", command.c_str(),reply.c_str());
	}
	//添加复制节点
	
	std::string command = "{\"replSetInitiate\":{\"_id\":\"COOL\",\"members\":[{\"_id\":0,\"host\":\"10.90.15.198:27017\"},{\"_id\":1,\"host\":\"10.90.15.199:27017\"},{\"_id\":2,\"arbiterOnly\":true,\"host\":\"10.90.15.200:27017\"}]}}";
	std::string reply;
	ulret = h3c_cloud_mongodb_api::instance().mongodb_do_command("admin", command, reply);
	if (ulret != ERROR_COMMON_SUCCEED){
		H3C_CLOUD_MAN_LOG2(H3C_LOG_ERROR, "fail create json  info [%s] [%s]", command.c_str(), reply1.c_str());
	}
	//再次检查
	command = "{\"replSetGetStatus\":1}";
	reply;
	ulret = h3c_cloud_mongodb_api::instance().mongodb_do_command("admin", command, reply);
	if (ulret != ERROR_COMMON_SUCCEED){
		H3C_CLOUD_MAN_LOG2(H3C_LOG_ERROR, "fail create json  info [%s] [%s]", command.c_str(), reply2.c_str());
	}
	return ulret;
}
#上面测试接口三个命令返回的参数
{ "info" : "run rs.initiate(...) if not yet done for the set", "ok" : 0.0, "errmsg" : "no replset config has been received", "code" : 94, "codeName" : "NotYetInitialized" }

{ "ok" : 1.0 }

{ "set" : "COOL", "date" : { "$date" : 1573528438228 }, "myState" : 2, "term" : 0, "heartbeatIntervalMillis" : 2000, "optimes" : { "lastCommittedOpTime" : { "ts" : { "$timestamp" : { "t" : 0, "i" : 0 } }, "t" : -1 }, "appliedOpTime" : { "ts" : { "$timestamp" : { "t" : 1573528434, "i" : 1 } }, "t" : -1 }, "durableOpTime" : { "ts" : { "$timestamp" : { "t" : 1573528434, "i" : 1 } }, "t" : -1 } }, "members" : [ { "_id" : 0, "name" : "10.90.15.198:27017", "health" : 1.0, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 73, "optime" : { "ts" : { "$timestamp" : { "t" : 1573528434, "i" : 1 } }, "t" : -1 }, "optimeDate" : { "$date" : 1573528434000 }, "infoMessage" : "could not find member to sync from", "configVersion" : 1, "self" : true }, { "_id" : 1, "name" : "10.90.15.199:27017", "health" : 1.0, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 4, "optime" : { "ts" : { "$timestamp" : { "t" : 1573528434, "i" : 1 } }, "t" : -1 }, "optimeDurable" : { "ts" : { "$timestamp" : { "t" : 1573528434, "i" : 1 } }, "t" : -1 }, "optimeDate" : { "$date" : 1573528434000 }, "optimeDurableDate" : { "$date" : 1573528434000 }, "lastHeartbeat" : { "$date" : 1573528438080 }, "lastHeartbeatRecv" : { "$date" : 1573528437780 }, "pingMs" : 1, "configVersion" : 1 }, { "_id" : 2, "name" : "10.90.15.200:27017", "health" : 1.0, "state" : 7, "stateStr" : "ARBITER", "uptime" : 4, "lastHeartbeat" : { "$date" : 1573528438080 }, "lastHeartbeatRecv" : { "$date" : 1573528438173 }, "pingMs" : 0, "configVersion" : 1 } ], "ok" : 1.0 }

注:接口配置的详细参数

//std::string command 的详细配置-->用于这个命令的cfg参数{\"replSetInitiate\":\"cfg\"}
{
	"_id" : "COOL",
	"version" : 1,
	"protocolVersion" : NumberLong(1),
	"members" : [
		{
			"_id" : 0,
			"host" : "10.90.15.198:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "10.90.15.199:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "10.90.15.200:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
	],
}

mongodb.conf配置文件

#mongodb.conf mongo数据库配置文件
# 是否启用认证
auth= true
# 集群的私钥的完整路径,只对于Replica Set 架构有效(noauth = true时不用配置此项)

#在一台服务器上生成私钥
# openssl rand -base64 745 > mongodb-keyfile
#修改私钥的权限为可读写
#chmod 600 mongodb-keyfile
#将私钥拷贝到其余的服务器上
#scp mongodb-keyfile root@xxx.xxx.xxx.xxx:/xxxx/configdb 
keyFile = /data/configdb/mongodb-keyfile 

# 设置oplog的大小(MB)
oplogSize=2048
# 设置副本集名称
replSet=COOL
# 绑定ip
bind_ip = 0.0.0.0
# 监听端口
port=27017

mongo docker-compose 模板文件,这里使用docker 安装mongo

# Use root/example as user/password credentials
version: '3.1'

services:
  mongo:
    image: mongo
    restart: always
    privileged: true
    ports:
      - 27017:27017
    volumes:
      - ../data:/data/db
      - ../config:/data/configdb
     
    command: mongod -maxConns=4000 --config /data/configdb/mongodb.conf
      
  mongo-express:
    image: mongo-express
    networks:
      #- default
      - cloudface_net
    restart: always
    ports:
      - 27109:8081