mongo小结(>=2.2)
1、存储模式:面向集合存储,模式自由; GridFS大文件存储(16M)
2、容灾类型:主从复制(Replication)、Replica Set(自动选取主节点)、Sharding + Replica Set。
说明:mongo的Replication采用日志+批量更新方式,效率比直接更新高,Replication更新期间,从节点读性能受影响(锁机制导致)。
3、支持CRUD 和 Fast In-Place Updates(文档内更新)。
说明:Fast In-Place Updates支持快速更新文档自身内容,对于不影响文档大小的更新,效率比覆盖更新整个文档效率高。为了支持改变文档大小的文档内更新,mongo内部采用padding,即采用比文档略大的空间存储文档,当更新导致文档大小改变时,如改变大小不超过padding大小,就地更新,无须另外存储。padding比例由mongo自身决定。
4、读写锁,写锁优先
说明:mongo的锁机制对于解释mongo运行效率很重要。常见需要写锁的操作:insert、update、remove、eval(执行命令或脚本)、createIndex(创建索引需锁定整个collection,数据大时,相当耗时)、replication、TTL的定期删除。
5、存储机制:mmap file + 内存索引。完全由OS处理缓存。磁盘空间预分配(默认2G)。
说明:mongo将内存管理和缓存都交给OS。内存优先让给索引使用。当索引大于内存大小时,将影响各种操作。当"工作集"(热门数据)+索引 大于 内存时,查询性能受影响。
6、集合类型:普通集合、TTL Collection(淘汰过期数据)、 Capped Collection(定长集合,FIFO)
7、同步:拷贝集合数据+日志同步
8、相对丰富的运维工具和shell客户端
使用示例
// this header should be first to ensure that it includes cleanly in any context #include "mongo/client/dbclient.h" #include <iostream> #include <vector> #include <string> #ifndef verify # define verify(x) MONGO_verify(x) #endif using namespace std; using namespace mongo; int connect_mongo(DBClientConnection* conn, const string& ip, const string& port) { try{ if( conn->getServerAddress().empty() ){ // not init string errmsg; if( ! conn->connect( ip + ":" + port , errmsg ) ){ printf("FAIL connect mongo, %s", errmsg.c_str()); return -1; } } if (conn->isFailed()) { string errmsg; if ( ! conn->connect( ip + ":" + port , errmsg ) ) { printf("FAIL connect mongo, %s", errmsg.c_str()); return -1; } } } catch( DBException& e ) { printf("MONGO Exception(connect): %s", e.what()); return -1; } catch ( std::exception& e ) { printf("MONGO Exception(connect): %s", e.what()); return -1; } catch( ... ){ printf("MONGO Exception(connect): NULL"); return -1; } return 0; } int set_mongo(DBClientConnection* conn, const string& dbname, const string& id, const string& value) { try{ mongo::BSONObjBuilder b; long long curtime = time(NULL); Date_t date( (curtime - curtime % (3600*24) + ( random() % 6 + 2) * 3600) * 1000 ); // limit ttl deleting time to 2:00-8:00. b.append( "_id", id ); b.append( "value", value); b.append( "ts", date); //cout<< b.obj() << endl; conn->update( dbname , BSONObjBuilder().append( "_id" , id ).obj(), b.obj(), true ); } catch( DBException& e ) { printf("MONGO Exception(set): %s", e.what()); return -1; } catch ( std::exception& e ) { printf("MONGO Exception(set): %s", e.what()); return -1; } catch( ... ){ printf("MONGO Exception(set): NULL"); return -1; } return 0; } int get_mongo(DBClientConnection* conn, const string& dbname, const string& id, string& value) { try{ BSONObj obj = conn->findOne( dbname, BSONObjBuilder().append( "_id" , id ).obj()); if( !obj.isEmpty() ){ value = obj.getStringField("value"); } } catch( DBException& e ) { printf("MONGO Exception(get): %s", e.what()); return -1; } catch ( std::exception& e ) { printf("MONGO Exception(get): %s", e.what()); return -1; } catch( ... ){ printf("MONGO Exception(get): NULL"); return -1; } return 0; } int mget_mongo(DBClientConnection* conn, const string& dbname, const vector<string>& ids, vector<string>& values) { try{ mongo::BSONObjBuilder b; b.append( "$in", ids); auto_ptr<DBClientCursor> cursor = conn->query( dbname, BSON( "_id" << b.obj() )); while ( cursor->get() && cursor->more() ) { BSONObj obj = cursor->next(); if( !obj.isEmpty() ){ values.push_back(obj.getStringField("value")); } } } catch( DBException& e ) { printf("MONGO Exception(get): %s", e.what()); return -1; } catch ( std::exception& e ) { printf("MONGO Exception(get): %s", e.what()); return -1; } catch( ... ){ printf("MONGO Exception(get): NULL"); return -1; } return 0; } int del_mongo(DBClientConnection* conn, const string& dbname, const string& id) { try{ conn->remove( dbname, BSONObjBuilder().append( "_id" , id ).obj()); } catch( DBException& e ) { printf("MONGO Exception(del): %s", e.what()); return -1; } catch ( std::exception& e ) { printf("MONGO Exception(del): %s", e.what()); return -1; } catch( ... ){ printf("MONGO Exception(del): NULL"); return -1; } return 0; } void Print(DBClientConnection& conn, const string& dbname) { auto_ptr<DBClientCursor> cursor = conn.query( dbname , BSONObj() ); int count = 0; while ( cursor->more() ) { count++; BSONObj obj = cursor->next(); std::cout<< obj << std::endl; } } int main( int argc, const char **argv ) { const char *port = "27000"; string host( "127.0.0.1" ); if ( argc < 3 ) { std::cout << argv[0] << " dbname host [port]" << endl; return EXIT_FAILURE; } const char* dbname = argv[1]; if( argc >= 3){ host = string(argv[2]); } if( argc >= 4){ port = argv[3]; } { DBClientConnection conn( false , 0 , 2 ); if( connect_mongo(&conn, host, port) != 0) { exit(-1); } string id = "test123"; string value = "test456"; del_mongo(&conn, dbname, id); set_mongo(&conn, dbname, id, value); string ret_val; get_mongo(&conn, dbname, id, ret_val); if( value != ret_val){ cout<<"TEST FAIL: " << value << " : " << ret_val <<endl; } } cout << "test finished!" << endl; return EXIT_SUCCESS; }
参考
官方文档: http://docs.mongodb.org/master/MongoDB-Manual-master.pdf
MongoDB 2.2 的 Time To Live (TTL) 集合: http://www.oschina.net/translate/mongodb-time-to-live-ttl-collections
C++客户端代码的示例