Mongodb简单优化

MongoDB WiredTiger引擎调优技巧

  • 调优Cache Size

WiredTiger最重要的调优参数就是cache规模。默认,MongoDB3.x开始会保留可用物理内存的50%(3.2是60%)作为数据cache。虽然,默认的设置可以应对大部分的应用,通过调节为特定应用找到最佳配置值还是非常值得的。cache的规模必须足够大,以便保存应用整个工作集(working set)。

除了这个cacheMongoDB在做诸如聚合、排序、连接管理等操作时需要额外的内存。因此,必须确保有足够的内存可供使用,否则,MongoDB进程有被OOM killer杀死的风险。

调节这个参数,首先要理解在默认配置下,cache的使用情况。运行以下命令,可以获得cache统计:

db.serverStatus().wiredTiger.cache
{
   "tracked dirty bytes in the cache" : 409861,
   "tracked bytes belonging to internal pages in the cache" : 738956332,
   "bytes currently in the cache" : 25769360777,
   "tracked bytes belonging to leaf pages in the cache" : 31473298388,
   "maximum bytes configured" : 32212254720,
   "tracked bytes belonging to overflow pages in the cache" : 0,
   "bytes read into cache" : 29628550664,
   "bytes written from cache" : 34634778285,
   "pages evicted by application threads" : 0,
   "checkpoint blocked page eviction" : 102,
   "unmodified pages evicted" : 333277,
   "page split during eviction deepened the tree" : 0,
   "modified pages evicted" : 437117,
   "pages selected for eviction unable to be evicted" : 44825,
   "pages evicted because they exceeded the in-memory maximum" : 74,
   "pages evicted because they had chains of deleted items" : 33725,
   "failed eviction of pages that exceeded the in-memory maximum" : 1518,
   "hazard pointer blocked page eviction" : 34814,
   "internal pages evicted" : 21623,
   "maximum page size at eviction" : 10486876,
   "eviction server candidate queue empty when topping up" : 8235,
   "eviction server candidate queue not empty when topping up" : 3020,
   "eviction server evicting pages" : 191708,
   "eviction server populating queue, but not evicting pages" : 2996,
   "eviction server unable to reach eviction goal" : 0,
   "pages split during eviction" : 8821,
   "pages walked for eviction" : 157970002,
   "eviction worker thread evicting pages" : 563015,
   "in-memory page splits" : 52,
   "percentage overhead" : 8,
   "tracked dirty pages in the cache" : 9,
   "pages currently held in the cache" : 1499798,
   "pages read into cache" : 2260232,
   "pages written from cache" : 3018846
}

第一个要关注的数值试,`cache`中脏数据的百分比。如果这个百分比比较高,那么调大`cache`规模很有可能可以提升性能。如果应用是重读的,可再关注`bytes read into cache`这个指标。如果这个指标比较高,那么调大`cache`规模很有可能可以提升读性能。

  • 动态调整WiredTiger

db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=xxG"})

  • 控制Read/Write Tickets

WiredTiger使用tickets来控制可以同时被存储引擎处理的读/写操作数。默认值是128,在大部分情况下表现良好。如果这个值经常掉到0,所有后续操作将会被排队等待。例如,观察到读tickets下降,系统可能有大量长耗时的操作(未索引操作)。如果你想找出有哪些慢操作,可以用一些第三方工具。你可以根据系统需要和性能影响上下调节tickets

运行以下命令可以确认tickets的使用情况:

db.serverStatus().wiredTiger.concurrentTransactions
{
   "write" : {
      "out" : 0,
      "available" : 128,
      "totalTickets" : 128
   },
   "read" : {
      "out" : 3,
      "available" : 128,
      "totalTickets" : 128
   }
}

  • 可以动态调节tickets
db.adminCommand( { setParameter: 1, wiredTigerConcurrentReadTransactions: xx } )
db.adminCommand( { setParameter: 1, wiredTigerConcurrentWriteTransactions: xx } )

一次Mongodb异常宕机崩溃

一次 mongoDB 异常崩溃地址串

  • mongos 退出时的日志如下表所示,报 “Failed to mlock: Cannot allocate memory” 错误。同时,分析故障发生时分片集群中多个主节点的日志,发现都有多个连接在执行耗时较长的查询操作。
2017-12-14T18:01:43.047+0800 I ASIO     [NetworkInterfaceASIO-TaskExecutorPool-19-0] Successfully connected to 192.168.1.100:27017, took 291ms (10 connections now open to 192.168.1.100:27017)
2017-12-14T18:01:43.048+0800 I ASIO     [NetworkInterfaceASIO-TaskExecutorPool-19-0] Connecting to 192.168.1.200:27017
2017-12-14T18:01:43.048+0800 I ASIO     [NetworkInterfaceASIO-TaskExecutorPool-19-0] Connecting to 192.168.1.200:27017
2017-12-14T18:01:43.050+0800 F -       [NetworkInterfaceASIO-TaskExecutorPool-22-0] Failed to mlock: Cannot allocate memory
2017-12-14T18:01:43.050+0800 I -        [NetworkInterfaceASIO-TaskExecutorPool-22-0] Fatal Assertion 28832 at src/mongo/base/secure_allocator.cpp 246
2017-12-14T18:01:43.050+0800 I -        [NetworkInterfaceASIO-TaskExecutorPool-22-0] …
2017-12-14T18:01:43.054+0800 F -        [NetworkInterfaceASIO-TaskExecutorPool-22-0] Got signal: 6 (Aborted).

  • 故障分析已经重现
    初步分析触发故障的原因是大量慢查询导致了 mongos 与 mongod 之间的连接长时间没有释放,使得连接池中的连接无法复用,开始新建连接,而新建连接需要分配一定的锁定内存。mongos 需要分配的锁定内存超过 max locked memory 的限制,于是程序崩溃退出。max locked memory 的默认值如下图所示是 64KB(这个限制是对整个进程的,而且限制只对普通用户起作用,对 root 用户不起作用).
[mongodb@mongodb4 ~]$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 63717
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 59999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 59999
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

  • 解决方法

1、调整 max locked memory 的大小。根据之前的分析发现是 mongos 对锁定内存的分配超出了操作系统的限制,所以可以通过调整该限制来解决问题。官方在修复 bug 之前,也是推荐增加 max locked memory 的限制。调整方式如下:ulimit -l 96,该命令将限制值设置为 96KB。具体调整为多少官方没有说明,之后分析源码发现每一个连接占用的锁定内存是 60 个字节,但锁定内存不仅仅在此处用到。所以如果每个连接的请求都发生慢查询,那么 64KB 理论上支持的最大连接数是 1092 个

2、升级到 3.4.6 及以上版本。当时线上 mongos 和 mongod 版本是 3.4.4,我们将 mongos 和 mongod 升级到 3.4.9,使用相同的方式进行测试,发现不会发生类似故障。
MongoDB 官网有 issue 提到这个问题 SERVER-28997,这是 3.4.4 版本的 bug,而我们当时线上环境使用的正好也是 3.4.4 版本,之后 3.4.6 版本已经修复。官方描述是:

SasLTCHa1clipse会话有一个将从缓存中拔出的加密。
RADIONTS在默认构造函数中分配安全存储,因此可以填充它们。
相反,SASLTCHAK1clitTalk和缓存应该将SysDypRTs存储到SCRAMSecret。

生产环境shard配置文件分享

logpath=/home/mongodb/log/shard11.log
pidfilepath=/home/mongodb/shard11.pid
logappend=true
bind_ip=192.168.128.10
port=27017
fork=true
replSet=shard1
dbpath=/home/mongodb/data/shard11
oplogSize=10000
noprealloc=true
shardsvr=true
directoryperdb=true
storageEngine = wiredTiger
wiredTigerCacheSizeGB = 3
syncdelay = 30
wiredTigerCollectionBlockCompressor = snappy

Mongo日志自动分卷脚本

  • mongos_log.sh 可以吧mongos、config都添加上,然后在添加上linux 的定时任务。则每天定时日志分卷
[mongodb@mongodb4 ~]$ more mongos_log.sh
/home/mongodb/mongodb_3.2.12/bin/mongo 192.168.128.19:27021/admin <

错误的Mongodb分片的选择

  • Mongodb运行现状

    • mongodb集群是3台服务器三个副本集群,每台服务器配置mongos、confi、mongod(主、从、仲裁)5个进程
  • 场景说明

  • 近期线上Mongodb服务器某一台服务器负载情况特别高,单个集合shard主节点占用CPU负载很高,使用mongotop 和mongostat命令分析,发现某个副本集合,要比其他两个集合要操作频繁,而从影响线上数据入库导致延迟。

  • 原因

    • 是因为当初创建表时,使用的start_time来作为片键使用的是hash,也就导致入库hash到某个集合时,频繁操作入库都是在这个shard集群上面,也就导致服务器负载压力特别高
  • 解决方法

    • 使用多字段创建分键,先导出数据、然后删除表、创建分片、在导入数据。

你可能感兴趣的:(Mongodb简单优化)