四时宝库

程序员的知识宝库

MongoDB 使用技巧记录(六)(mongodb使用场景 简书)

MongoDB 使用技巧记录(六)

一:mongo 优化

mongodb优化

1.尽量少用in的方式查询,尤其是在shard上,他会让你的查询去被一个shand上跑一次,

如果逼不得已要用的话再每个shard上建索引。

优化in的方式是把in分解成一个一个的单一查询。速度会提高40-50倍。

2.和大部分数据库优化一样,查询量大,并发大的时候通过前端加缓存解决。

3.在写入mongodb的时候,可以加入safe用安全模式写。

这么的话,在一个会话中就算有一个shard或者一个主切换了,程序会返回错误。从新写入。不然不报错会丢数据。

使用safe以后,在mongosniffer抓包会在每次写入和更新之后写一个{getlasterror:1}的返回。

4.mongodb在做banlace的时候,会锁住在迁移的数据,不能读。

因为mongos不知道要去那个shard上去找数据。64M的chunks迁移快的时候1秒,慢的时候3-5秒

5. sharding key通常就是会频繁使用的索引

6. increamenting sharding key(增量sharding-key)适合于可划分范围的字段,比如integer、float、date类型的,查询时比较快

7. random sharding key(随机sharding-key)适用于写操作频繁的场景,而这种情况下如果在一个shard上进行会使得这个shard负载比其他高,不够均衡,故而希望能hash查询key,将写分布在多个shard上进行

8. 枚举类型的字段最适合不过啦 :)

9. 考虑复合key作为sharding key

9. 总的原则是查询快,尽量减少跨shard查询,balance均衡次数少。

10.mongodb默认是单条记录4M,尤其在使用GFS的时候,一定要注意shrading-key的设计。

不合理的sharding-key会出现,多个文档,在一个chunks上,同时,因为GFS中存贮的往往是大文件,导致mongodb在做balance的时候无法通过sharding-key来把这多个文档分开到不同的shard上,

这时候mongodb会不断报错Tue Jan 10 15:24:59 [conn27669] Uncaught std::exception: St9bad_alloc, terminating。最后导致mongodb倒掉。

解决办法:加大chunks大小(治标),设计合理的sharding-key(治本)。

12.在一个shard中要注意PRIMARY,SECONDARY,ARBITER的设计。

例如,我们公司环境中的1P,2S,2A的环境,PRIMARY倒掉以后有一定几率出现2A同时支持不同的SECONDARY,导致一直无法选择出新的PRIMARY。

表现是mongos查询报错:

> db.users.find()

error: { "$err" : "error querying server: 10.10.21.163:27018", "code" : 13633 }

> db.users.find()

error: {

"$err" : "DBClientBase::findOne: transport error: 10.10.21.163:27018 query: { setShardVersion: \"test.users\", configdb: \"10.7.3.228:27019\", version: Timestamp 11000|1, serverID: ObjectId('4e2f64af98dd90fed26585a4'), shard: \"shard0000\", shardHost: \"10.10.21.163:27018\" }",

"code" : 10276

}

> db.users.find()

error: { "$err" : "socket exception", "code" : 11002 }

手动添加的话一个 SECONDARY还是报错

> db.runCommand({addshard:"10.10.21.164:27017"});

{

"ok" : 0,

"errmsg" : "host is part of set: set163164 use replica set url format /,,...."

}

解决办法:重新启动其中一个SECONDARY问题解决。

具体操作如下:

use admin

var cfg={_id:"set162163164", members:[{_id:0,host:"10.10.21.162:27018"},

{_id:1,host:"10.10.21.163:27017"}, {_id:2,host:"10.10.21.164:27017",arbiterOnly:true} ]}

rs.initiate(cfg)

rs.conf()

use admin

#db.runCommand({addshard:"set162163164/10.10.21.162:27018,10.10.21.163:27017,10.10.21.164:27017"}) #正常添加3台

db.runCommand({addshard:"set162163164/10.10.21.162:27018,10.10.21.163:27017"}) #arbiter

db.runCommand({addshard:"10.10.21.165:27018"})

db.runCommand({enableSharding:"test"})

db.runCommand({shardcollection:"test.users",key:{_id:1}})

13.通过ulimit -a来控制mongodb使用内存的大小

ulimit 是控制着所有进程的内存大小,怎么针对MongoDB进行控制呢?

其实可以变通的,我们在自己linux里使用一个用户来运行MongoDB,其它程序用其它用户进行运行。因为ulimit是可以限制指定用户资源的.

通过ulimit -a来查看所有可以修改的资源

ulimit -a @root

-t: cpu time (seconds) unlimited

-f: file size (blocks) unlimited

-d: data seg size (kbytes) unlimited

-s: stack size (kbytes) 8192

-c: core file size (blocks) 0

-m: resident set size (kbytes) unlimited

-u: processes 1024

-n: file descriptors 1024

-l: locked-in-memory size (kb) 64

-v: address space (kb) unlimited

-x: file locks unlimited

-i: pending signals 15661

-q: bytes in POSIX msg queues 819200

-e: max nice 0

-r: max rt priority 0

这里我们修改的是 ulimit -v: address space(kb) 选项 也就是用户进程的最大虚拟地址空间。

我们新建个用户cb,在启动mongod之前

ulimit -v 1000000 修改最大虚拟地址空间为1G

然后运行mongod 端口为10000,并执行1000W的数据插入脚本。

再使用root用户,不对ulimit进行任何修改,开起另外一个mongod 端口为20000 ,也同时进行1000W的数据插入.

1.查询优化

确认你的查询是否充分利用到了索引,用explain命令查看一下查询执行的情况,添加必要的索引,避免扫表操作。

2.搞清你的热数据大小

可能你的数据集非常大,但是这并不那么重要,重要的是你的热数据集有多大,你经常访问的数据有多大(包括经常访问的数据和所有索引数据)。使用MongoDB,你最好保证你的热数据在你机器的内存大小之下,保证内存能容纳所有热数据。

3.选择正确的文件系统

MongoDB的数据文件是采用的预分配模式,并且在Replication里面,Master和Replica Sets的非Arbiter节点都是会预先创建足够的空文件用以存储操作日志。这些文件分配操作在一些文件系统上可能会非常慢,导致进程被Block。所以我们应该选择那些空间分配快速的文件系统。这里的结论是尽量不要用ext3,用ext4或者xfs。

4.选择合适的硬盘

这里的选择包括了对磁盘RAID的选择,也包括了磁盘与SSD的对比选择。

5.尽量少用in的方式查询,尤其是在shard上,他会让你的查询去被一个shand上跑一次,

如果逼不得已要用的话再每个shard上建索引。

优化in的方式是把in分解成一个一个的单一查询。速度会提高40-50倍

6.合理设计sharding key

increamenting sharding key(增量sharding-key)适合于可划分范围的字段,比如integer、float、date类型的,查询时比较快

random sharding key(随机sharding-key)适用于写操作频繁的场景,而这种情况下如果在一个shard上进行会使得这个shard负载比其他高,不够均衡,故而希望能hash查询key,将写分布在多个shard上进行

考虑复合key作为sharding key, 总的原则是查询快,尽量减少跨shard查询,balance均衡次数少。

mongodb默认是单条记录16M,尤其在使用GFS的时候,一定要注意shrading-key的设计。

不合理的sharding-key会出现,多个文档,在一个chunks上,同时,因为GFS中存贮的往往是大文件,导致mongodb在做balance的时候无法通过sharding-key来把这多个文档分开到不同的shard上,

这时候mongodb会不断报错

[conn27669] Uncaught std::exception: St9bad_alloc, terminating。最后导致mongodb倒掉。

解决办法:加大chunks大小(治标),设计合理的sharding-key(治本)。

7.mongodb可以通过profile来监控数据,进行优化。

查看当前是否开启profile功能

用命令db.getProfilingLevel() 返回level等级,值为0|1|2,分别代表意思:0代表关闭,1代表记录慢命令,2代表全部

开启profile功能命令为

db.setProfilingLevel(level); #level等级,值同上

level为1的时候,慢命令默认值为100ms,更改为db.setProfilingLevel(level,slowms)如db.setProfilingLevel(1,50)这样就更改为50毫秒

通过db.system.profile.find() 查看当前的监控日志


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接