zoukankan      html  css  js  c++  java
  • MySQL thread pool【转】

    本文来自:http://blog.chinaunix.net/uid-26896862-id-3993773.html

    刚刚经历了淘宝的双11,真实感受到了紧张的氛围。尽管DB淡定的度过,但是历程中的波折,可谓惊心动魄。其中MySQL在大量连接(万级)的场景下,表现出性能远远低于预期,并且出现明显的波动,成为一个非常重要的问题。问题虽然解决,但是后续的思考和方法的探索,仍然继续。以下是在MySQL层增加Thread pool方式,解决大量连接问题。

    1、《MySQL Thread Pool: Problem Definition》

    MySQL企业版在5.5中,引入了Thread pool方案。本文主要是分析现有方式存在的问题,并引入Thread pool方式以及需求。主要解决MySQL传统连接设计中one-to-one方式(一个连接使用一个线程服务)存在两个方面的问题:

    1.1 CPU资源限制

    在连接数非常多,并发较大时,CPU可用资源会成为MySQL的连接线程的瓶颈,导致MySQL性能降低。有两个原因:一个是并发数较大时,CPU的cache命中率降低,以及并发线程创建消耗内存资源,可能导致swap影响MySQL的性能;另一个原因是并发较大时,会导致通过临界资源时,产生大量的锁竞争。这些问题在系统层都很难解决,只能通过应用层解决。

    1.2 Innodb mutex锁

    在并发较大时,会引起Innodb的mutex锁争用。当前解决方法是通过innodb_thread_concurrency参数,但是该参数自身也存在锁争用,同样影响了MySQL的性能。在我们的优化历程中,也尝试通过优化该参数,来解决并发情况下,性能降低的问题。但是测试过程中发现,会有大量的连接等待kernel mutex锁,但是持续的压力会导致MySQL的thread running,最终导致MySQL不可用。

    Thread pool主要从四个方面考虑:减少SQL并发,使得有足够的资源;使用线程组,独立管理;使用优先级队列,限制并发执行的事务;避免死锁。

    在以上阐述的内容中,几乎涵盖了我们遇到的所有现象和问题,而性能影响会如此严重,是我们始料未及的。

    2、《MySQL Thread Pool: Scalability solution》

    基于上文中问题定义,本文主要讨论Thread pool的可扩展性解决方案。为了解决并发连接数问题,通常考虑会创建一个线程池,但是会引入可扩展性问题:每个连接或线程建立时,会对公用的数据结构加锁,修改连接或线程的状态信息。这样无异于重新引入热点。

    为了避免引入新的问题,Thread pool使用线程组,每个线程组管理组内的连接和线程,线程组之间互相不受影响。并且确保每个线程组内最多有一个活跃的线程连接,这样连接和线程建立时,仅对单个线程组内的数据结构加锁,文中称之为分治法。

    在文章回复中,有一个问题非常重要:线程组的引入,会出现当等待线程组时,请求不能进入而阻塞连接,而该问题会通过定时器的方式解决。另一个问题是:通过限制每个用户的连接数,而MySQL层通过innodb_thread_concurrency参数控制,来控制并发连接数。对于第二个问题,当应用达到一定重量级时,限制用户连接数变得比较困难。假设有几千台应用服务器,每个应用服务器1~2个数据库连接,同样会出现并发连接过多的问题。也就是说通过用户连接数限制,治标不治本。

    3、《MySQL Thread Pool: Limiting number of concurrent statement executions》

    上文回复中,提出当线程组引入后,SQL语句可能会导致线程组的等待,阻塞大量查询。本文中针对该问题,提出了通过定时器的方式解决。当SQL查询执行超过定时器的时间,线程组将会设置为不可用。

    此外,当查询由于锁被阻塞时,线程会等待超时时间,然后处理新的查询请求,从而保证了线程组的可用。

    4、《MySQL Thread Pool: Limiting number of concurrent transactions》

    对于事务的并发控制,Thread pool采用优先级队列的方式解决。为了避免大事务导致线程组不可用,引入了thread_pool_prio_kickup_timer参数,当事务超过参数设置的超时时间时,等待线程组的查询会被移到高优先级队列中。为了避免过多的移动,Thread pool限制每个线程组在10ms内最多移动一次。

    通过优先级队列,可以很大程度上解决因为事务阻塞,而产生大量查询超时的问题,还解决了其他线程组空闲的情况。

    5、《MySQL Thread Pool: When to use?》

    Thread pool的原理和实现在以上文章中进行了详细的解释,但是什么时候用呢?本文指出根据threads_running的监控值,来判断是否使用Thread pool。当threads_running值超出了MySQL的处理能力时,Thread pool将会保护MySQL server。

    此外,Thread pool和innodb_thread_concurrency参数一起使用,可以更好的控制并发。Thread pool主要在Server层,在事务开始之前进行限制,innodb_thread_concurrency在事务处理中进行控制。

    特别指出,如果查询为短查询,Thread pool会非常有效。如果查询为长查询,Thread pool会有性能影响。

    6、《MySQL Thread Pool vs. Connection Pool》

    针对文章2中回复的第二个问题,本文详细解释了Thread pool和Connection pool两者的区别。Thread pool主要是MySQL端采取的线程控制,用于限制MySQL实际处理的SQL并发。而Connection pool是在应用的客户端来限制,连接到MySQL Server的线程数。

    在某些情况下,Connection pool并非所有的连接都有活跃的事务,但是会在MySQL Server中建立大量的连接。而通过Thread pool,可以减少MySQL Server的连接数。

    7、《MySQL Thread Pool: Optimal configuration》

    本文主要介绍Thread pool使用的参数进行详细的说明,主要包括:thread_pool_size指定线程池大小,默认值为16;thread_pool_stall_limit执行线程池超时时间,默认值为6(60ms);thread_pool_prio_kickup_timer限制优先级队列移动的超时时间,默认值为1000(1s);thread_pool_algorithm指定线程池算法,暂不支持;thread_pool_max_unused_threads查看当前最大未使用的线程数。

    在实际使用中,根据数据库服务器的性能,MySQL Server的使用情况,以及应用查询的情况,调整这些参数,从而达到最佳的性能。

    8、《MySQL Thread Pool: Benchmarking》

    本文通过压力测试,比较使用Thread pool前后,性能的影响。通过测试结果可知,使用Thread pool在连接并发数较大时,性能可以稳定在较高水平,并没有由于连接数的增加,导致MySQL性能的骤减。

    官方测试结果如下图所示,

     

     

    结论

    Thread pool的引入,解决了MySQL传统连接设计中one-to-one方式带来的不足。此外,使用线程组的方式,避免引入新的可扩展问题;使用定时器,解决长查询阻塞线程组的问题;通过优先级队列,解决大事务问题。

    从测试结果来看,Thread pool在连接并发数较大时,性能可以稳定在较高水平,而没有由于连接数的增加,导致MySQL性能的骤减。

    由于MySQL企业版未开放源码,只能通过黑盒测试进行评估。但是实现的原理和处理策略,对于评估开源Thread pool的实现,都非常有益。

    参考

    1、《MySQL Thread Pool: Problem Definition》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-problem-definition.html

    2、《MySQL Thread Pool: Scalability solution》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-scalability-solution.html

    3、《MySQL Thread Pool: Limiting number of concurrent statement executions》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-limiting-number-of.html

    4、《MySQL Thread Pool: Limiting number of concurrent transactions》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-limiting-number-of_21.html

    5、《MySQL Thread Pool: When to use?》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-when-to-use.html

    6、《MySQL Thread Pool vs. Connection Pool》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-vs-mysql-connection.html

    7、《MySQL Thread Pool: Optimal configuration》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-optimal-configuration.html

    8、《MySQL Thread Pool: Benchmarking》:http://mikaelronstrom.blogspot.com/2011/10/mysql-thread-pool-benchmarking.html

  • 相关阅读:
    Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
    Combine 框架,从0到1 —— 4.在 Combine 中使用通知
    Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
    Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
    使用 Swift Package Manager 集成依赖库
    iOS 高效灵活地配置可复用视图组件的主题
    构建个人博客网站(基于Python Flask)
    Swift dynamic关键字
    Swift @objcMembers
    仅用递归函数操作逆序一个栈(Swift 4)
  • 原文地址:https://www.cnblogs.com/zhoujinyi/p/4538393.html
Copyright © 2011-2022 走看看