1.问题背景

对于分布式数据库和分布式环境,高并发和高性能压力的情况下,出现线程创建失败等等问题也是十分常见的,这时候就十分考虑数据库管理员的经验,需要能快速的定位到问题和瓶颈所在,快速解决。本文也是作为一个最佳实践,告诉大家如何在高并发情况下定位问题,排除问题,解决瓶颈。

2.问题定位

SequoiaDB在集群环境中的 -10 错误码,在认真查阅节点的 diaglog 日志后,发现是操作系统 create thread 失败的问题。

如我们的测试环境下,SequoiaDB节点的 diaglog 的错误日志信息

阅读这个错误日志的内容,通过看到类似如下的关键信息

Failed to create new agent: boost::thread_resource_error: Resource temporaily unavailable
Failed to create new agent, probe = 30
Failed to create subagent thread, rc = -10
Failed to start session EDU, rc = -10

那么一般操作系统在创建线程时,会受限于哪些参数呢,主要有几个:文件句柄数限制、操作系统句柄数限制和内存资源。

1)文件句柄数

在linux 操作系统中,号称一切皆为文件,无论是进程、线程、socker 还是其他,最终都会被操作系统归为文件操作。操作系统或者进程,每申请一个资源,例如线程、socker,都会打开一个文件,那么这个文件打开状态,就可以简单理解为文件句柄。其中,“句柄数限制“代表操作系统或者某个进程所能够打开的最多文件的数量的限制。

大家有了这个概念后,我们再来看操作系统是如何对文件句柄数进行限制的。在操作系统中,有一个神奇的命令 - ulimit 这一个命令可以设置许多限制值,进程文件句柄数就是其中之一。

例如我们可以查看 root 用户的 ulimit 输出, -n open file = 1024 就是root 用户允许进程打开的最大文件句柄数。

此处我们需要注意,由于root 用户是Linux 中的管理员用户,所以如果root 用户的 ulimit open file 设置成 1024, 那么其他的用户,例如test、mysql 用户等,想将 ulimit opon file 设置成 大于 1024,是不行的

因此,普通用户的 ulimit 值修改前,必须要注意root用户的ulimit值,保证普通用户的ulimit值比root用户的设置值小。

2)操作系统句柄数

除了进程中的句柄数限制,整个操作系统的句柄数限制同样会对数据库运行产生影响。在句柄数限制下,因为一个操作系统,总不能无限地打开句柄的。所以又引入另外一个设置,操作系统最大打开的句柄数限制。

这个值在 centos 7 中,是被保存在 /proc/sys/fs/file-max 文件中。

如果操作系统总的句柄数已经达到上限,那么即使进程还没有启动几个线程,也会出现句柄不够的情况。

如果希望临时修改操作系统最大句柄数的设置,可以直接执行,即可: echo 2000000 >  /proc/sys/fs/file-max

如果希望永久修改操作系统最大句柄数的设置,可以编辑 /etc/sysctl.conf 文件,增加 fs.file-max = 2000000 内容,然后在root 用户中执行 sysctl -p 即可。

3)内存

针对内存资源的优化,在创建线程时,在Linux 中,是需要给它预先分配内存的 – 也叫 栈大小,用来存储线程中数据的值。

我们程序员都知道,内存主要分为两个大的部分,一个称为 “堆”,一个称为“栈”。在程序中,“堆”通常是程序用来保存常量和变量名字的,“栈”则通常是程序来用保存具体的变量数字的。

此前我们说到,如果系统内存不足,也是无法创建线程的。这个原因就是在于创建线程时,操作系统需要分配一块内存给线程,这个内存是多大呢,就是 ulimit 中 -s stack size 的大小。如果操作系统连 stack size 大小的内容都无法拿出来了,创建线程就会失败。

整个服务器资源,为什么这么一点内存都没有了?

其实如果仔细查看操作系统,你就会发现,那么多进程,每个进程又是那么多线程在运行,每个线程都在申请内存(注意,这块的内存是物理内存),内存不足正常的很。这个也容易让人联想到JVM 的OOM ,但是他们真的不是一回事,大家千万不要误会。

要解决这个问题也比较简单 – 直接粗暴?就是将 ulimit 中 -s stack size 调小一点,每个线程不要申请那么多内存了,操作系统的内存资源就会更加的充裕。毕竟程序、线程这些,都是用完就完了,不可能都永久占用内存的。

3.其他需要注意的点

除了上述解决方案,仍无法解决创建线程失败的额问题

执行 ulimit -a 命令,参数看起来也正常,但是系统是否是完成了设置?我们需要真正确认SequoiaDB进程的ulimit 参数是啥。

确认的方式有两种:

  • 在sdb的较新版本中,节点启动时的diaglog 日志,会打印它自己的
    ulimit 参数,读者可以去翻翻日志
  • 另外一种就更加直接,直接查看 linux 的系统记录。例如知道
    11910 进程的 PID 是 123456,就直接打开 /proc/123456/limits 文件,查看里面的内容,这样想不知道,都难

4.备注:关于句柄数和线程的命令

查看 某个进程总共开启了多少个 线程,可以

cat /proc/$PID/status | grep
Threads

pstree -p $PID ,然后+1,因为还有主进程

top -Hp $PID,然后查看头部 “Threads”参数

ps hH p $PID | wc -l

查看linux 目前总打开的句柄数

lsof -n|awk '{print $2}'|sort|uniq -c|sort
-nr|awk '{print $1}' | awk '{sum += $1};END {print sum}'

查看某个进程打开的总句柄数

lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr
|  grep  $PID

SequoiaDB报告创建线程失败的解决办法的更多相关文章

  1. windows下CreateDirectory创建路径失败的解决办法

    第一: 权限不够: SECURITY_ATTRIBUTES sa;SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor(&sd,SECURI ...

  2. tomcat启动失败的解决办法

    初次安装tomcat启动失败的解决办法: 1.CATALINA_HOME    C:\Program Files\apache-tomcat-8.5.242.path  %CATALINA_HOME% ...

  3. LoadLibrary加载动态库失败的解决办法

    from:http://blog.sina.com.cn/s/blog_62ad1b8101017qub.html 若DLL不在调用方的同一目录下,可以用LoadLibrary(L"DLL绝 ...

  4. Data Base sqlServer sa用户登陆失败的解决办法

    sqlserver sa用户登陆失败的解决办法 如下图以此模仿: 1.右键-属性 2.找到安全: 3.勾选如图: 4.sa用户密码重置: 5.服务重启:

  5. 微信公众平台Token验证失败的解决办法

    微信公众平台Token验证失败的解决办法 1.可查看url和token是否正确 2.查看服务器端口是否为80端口 3.你可以通过记录log日志来判断是否接受到微信提交过来的信息 1.$fp=fopen ...

  6. Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!)

    Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!) 1.控制面板中卸载所有带sql server的程序. 2.在C盘C:\Program Files中sqlserv ...

  7. npm install 错误 安装 chromedriver 失败的解决办法

    npm 安装 chromedriver 失败的解决办法npm 安装 chromedriver 时,偶尔会出错,错误提示类似于:npm ERR! chromedriver@2.35.0 install: ...

  8. WCF传输过大的数据导致失败的解决办法

    WCF传输过大的数据导致失败的解决办法   WCF服务默认是不配置数据传输的限制大小的,那么默认的大小好像是65535B,这才65KB左右,如果希望传输更大一些的数据呢,就需要手动指定一下缓冲区的大小 ...

  9. tomcat关闭后线程依然运行解决办法

    tomcat关闭后线程依然运行解决办法,设置线程为守护线程 守护线程与非守护线程 最近在看多线程的Timer章节,发现运用到了守护线程,感觉Java的基础知识还是需要补充. Java分为两种线程:用户 ...

随机推荐

  1. MySQL快速回顾:数据库和表操作

    前提要述:参考书籍<MySQL必知必会> 利用空闲时间快速回顾一些数据库基础. 4.1 连接 在最初安装MySQL,可能会要求你输入一个管理登录(通常为root)和一个口令(密码). 连接 ...

  2. 经济学人精读笔记7:动乱当道,你还想买LV吗?

    2020/2/24 经济学人精读笔记7:动乱当道,你还想买LV吗? 标签(空格分隔): 经济学人 Part 1 Luxury goods A tale of two handbags Purveyor ...

  3. 题解 Luogu P3370

    讲讲这题的几种做法: 暴力匹配法 rt,暴力匹配,即把字符串存起来一位一位判相等 时间复杂度$ O(n^2·m) $ 再看看数据范围 \(n\le10^5,m\le10^3\) 当场爆炸.当然有暴力分 ...

  4. 查看mysql是否锁表了

    1.查看表是否被锁: (1)直接在mysql命令行执行:show engine innodb status\G. (2)查看造成死锁的sql语句,分析索引情况,然后优化sql. (3)然后show p ...

  5. Go 与 PHP 的语法对比

    Go 是由 Google 设计的一门静态类型的编译型语言.它有点类似于 C,但是它包含了更多的优点,比如垃圾回收.内存安全.结构类型和并发性.它的并发机制使多核和网络机器能够发挥最大的作用.这是 Go ...

  6. javaSE学习笔记(15) ---缓冲流、转换流、序列化流

    javaSE学习笔记(15) ---缓冲流.转换流.序列化流 缓冲流 昨天复习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流.比如能够高效读写的缓冲流,能够转换编码的转换流,能够持久化 ...

  7. 关于在ssm下创建项目使用阿里巴巴下的druid数据库报错,出现无法创建连接的原因

    报错原因:外部jdbc.driver使用原生jdbc驱动jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql:///yonghedb?charact ...

  8. 【笔记】机器学习 - 李宏毅 - 8 - Backpropagation

    反向传播 反向传播主要用到是链式法则. 概念: 损失函数Loss Function是定义在单个训练样本上的,也就是一个样本的误差. 代价函数Cost Function是定义在整个训练集上的,也就是所有 ...

  9. Radmin Server v3.5.1 汉化破解绿色版 第四版

    下载:https://pan.baidu.com/s/1skOXffJ 使用方法:1.运行“安装.bat”,安装过程静默,安装后无托盘图标,不创建任何快捷方式.2.运行“设置.bat”,进入 radm ...

  10. mybatis+maven自动生成代码框架

    说明 通过可配置化,通过数据库自动生成model,da和mapper文件,这对于可定制化开发来说是非常有用的,减少了很多重复的工作. 添加依赖 <properties> <proje ...