hyperic mysql scaling 案例学习(数据库优化)

这是看了Sun 的communityone 上一篇介绍hyperic 在mysql 上scaling 的介绍写的笔记.

hyperic 是一个在大型数据中心用作服务器管理和监控的软件,Hyperic HQ 提供中心服务器来收集多台主机的状态和性能指标,并且在一个中心界面上管理…… 其他的好处看后面的参考资料
Hyperic 默认是支持三种数据库mysql,oracle,postgresql.

后面会用到的几个hyperic 内的术语:
Servers:  一台主机上一个特定的应用类型,比如mysql 服务,jboss 服务.
Services: 对应一个服务里面具体的某一个类型,比如mysql 里面的cpu 消耗,内存消耗,每个表的磁盘消耗.
Metrics: 每一个Services 一个时间点收集上来的数据,比如10:40 cpu 的消耗是60%.
Metrics data points(数据点): 一个时间点的某一个services 的具体数值, 比如上面的60%.

一种标准中等规模的度量数据:
远程管理300台主机,2100 Servers,21000 Services , 46万metric, 每分钟收集2万metric (平均值), 每天就是2千8百万数据点 (这个数据比较保守,性能收集间隔可以大一些.所以实际支持主机还可以多很多)

Hyperic Mysql 版本Scaling 技巧:

  1. 批量插入

    INSERT INTO TABLE (a,b,c) values (0, 0,0), (1,1,1),(2,2,2),(3,3,3),…,…

    减少和数据库来回次数,注意设置mysql 参数max_allowed_packet
    其他可选的提高插入速度的方法Set unique_checks=0, insert, set unique_checks=1 .
    Set foreign_key_checks=0, insert, set foreign_key_checks=1

  2. Batch Aggregate Inserter

    实际的数据点的数据一般很少看到,真正给监控人员看到的都是聚合后的数据(用线性图展现出来的)

    HQ agent 将收集到的聚合数据发送给HQ Server , 然后Server 并不马上保存这些数据,而server将几百个agent 的各种service 数据都放在queue 里面,然后批量插入.

    好处就是减少插入语句次数和connection 数. 减少CPU 消耗和服务器负载.调优之后的配置一般能达到700 agent . 3个workers , 每次批量插入BatchSize:2000 ,  QueueSize :4,000,000 , 每分钟可以插入2.2M 数据点. (还算是很保守的)

    这个技巧我觉得最厉害,这跟它表的结构也有关系, 它表储存原始数据都是三个列(time,measurement_id,value), 所以任何监控类型数据都可以存在这个表,所以它把数据放在queue 里面,然后批量的2000个才插入一次, 每次queue 里面总有几百万的数据,但是连接数却总能控制在个位数下,如果几百个agent 每种metric 都要从数据连接池里面取连接,而且还是永久性的连接,最少需要上千甚至上万个connection, 使用这种queue + batch 的方式,只有几个connection , 数据库跟hyperic server 服务器(它用的jboss) 性能都伸缩了不少. 数据中心非要这种方式的收集方法.

  3. 控制数据增长

    hyperic 监控的主机越多,service 越多,每分钟收集的数据量也就越多,控制详细数据和聚合数据的大小对于磁盘消耗显得很重要. 对于每个数据点收集是在hq_metric_data_xh_ys ,  一共有18个这样的表只保存2天的详细数据,每个表只保存一个小时的详细数据,然后循环,每个小时进行一次数据压缩,压缩的表已经不会进行insert 操作了,把数据压缩之后保存在eam_measurement_data_1h 中 (5列 $MEASUREMENT_ID , $TIMESTAMP , $VALUE , $MIN , $MAX ) , 每个小时只有一条数据(简单认为缩小了60倍吧),这种每个小时的数据保存14天,然后再把数据压缩到6个小时保存一条数据放在MEASUREMENT_DATA_6H 表中,保存31天,表结构完全一样,最后保存到MEASUREMENT_DATA_1D 表中,一天只保存一条数据.这个表你想保存多少年都可以了. 按照一台主机监控800台服务器上的16,000个metric 来看,一天也就16,000条数据,多少年都不成问题了.

    由于里面每个表的功能基本都是独立,一层一层的级别关系,所以进行很多操作的时候都没有锁,实时收集数据的表只有insert 操作,删除的表都是直接truncate 掉,压缩的表一个小时才做一次,用户查看的都是一个小时几个点的数据,而你又很容易看到几个月甚至几年的综合数据,比如像是可用性,CPU ,磁盘使用. 每种应用都找到自己的特殊表来用. 性能,负载,容量,历史数据都得到了很好的保存。 这个想法主要来自RRDtool ,一个主要用来时间系列的画图框架,主要用在nagios, cacti 等监控后台的图表展现上.

  4. 分区

    所有细节的表由hq_metric_data_xh_ys 表示,每两个表代表一天,一共9天,

    所有的数据归档压缩之后直接truncate ,而不是delete (这是针对mysql 5.1 之前没有partition 的功能而做,不知道以后会不会针对mysql 5.1 之后出个特别版), 应用程序上会自动计算应该insert 那个表,每个时间段该取那个表的数据. 所以insert 的表不会跟select 表和truncate 的表有冲突,3种表都自己做自己的工作.

    truncate 和 delete 的好处也有提到,这种partition 的设计还是要好好学学.

  5. 索引的选择

    选用InnoDB 是因为其基于主键的cluster index (和oracle 的IOT 一样), 优点就是select 更快,insert 也更快,索引占的磁盘也更少. 由于它全部都是基于时间点的顺序加入的,所以其cluster index, leaf index, data 都是基于同一个顺序在磁盘上访问,所以即使它不需要事务和锁,InnoDB 还是其最佳选择.

  6. SQL 的选择

    由于mysql 的view 不能够把子查询的sql 执行计划和外层的查询计划统一来计算,所以数据过滤操作要放在里面,外面再把表连接起来, 像是select xxx from (select *** from innertable1 union innertable2) as bigtable  where bigtable.xxx <??? 这种sql 执行起来就很慢, 而hyperic 要通过程序计算从那些表取数据,然后在外层连接起来. 像是这样

    SELECT begin AS timestamp, AVG(value) AS value, MAX(value) AS peak, MIN(value) AS low
    FROM
    (SELECT 1207631340000 + (2880000 * i) AS begin FROM EAM_NUMBERS WHERE i < 60) n,
    (SELECT * FROM HQ_METRIC_DATA_2D_1S
    WHERE timestamp between 1207767600000 and 1207804140000 AND
    measurement_id = 600332 UNION ALL
    SELECT * FROM HQ_METRIC_DATA_2D_0S
    WHERE timestamp between 1207724400000 and 1207767599999 AND
    measurement_id = 600332 UNION ALL
    SELECT * FROM HQ_METRIC_DATA_1D_1S
    WHERE timestamp between 1207681200000 and 1207724399999 AND
    measurement_id = 600332 UNION ALL
    SELECT * FROM HQ_METRIC_DATA_1D_0S
    WHERE timestamp between 1207638000000 and 1207681199999 AND
    measurement_id = 600332 UNION ALL
    SELECT * FROM HQ_METRIC_DATA_0D_1S
    WHERE timestamp between 1207631340000 and 1207637999999 AND
    measurement_id = 600332) EAM_MEASUREMENT_DATA
    WHERE timestamp BETWEEN begin AND begin + 2879999 AND measurement_id = 600332
    GROUP BY begin ORDER BY begin;

    不用管里面多复杂,简单来说就是里面要尽量多过滤数据(过滤条件都是程序通过时间计算的),外层得到最少的值才开始group 和order . (它从最差性能的sql -> 中等性能的sql -> 程序配合的最好性能的sql , 我花了几天时间还是只能理解个大概)

  7. ID 生成策略

    ID都是从10001开始生成,为hard-code 的ID 保留10000个空位,不使用auto-increment , 使用myisam 类型的hq_sequence 表来表示sequence , 

  8. 后面还有几个关于hibernate id 生成策略,建议性能参数和统计值,以及服务器建议配置等,不一一介绍了.
<p 整个hyperic ="" 在体系架构,编程特性和数据库设计上都设计的很高级,有很多功能是因为数据库特性限制而设计的,但同时也尽量发挥了每种数据库的最大特性,尤其是程序和数据库结合的设计提升性能很多,看得出特为数据中心的管理方式做了很多优化.<="" p="" style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">

参考资料:

  1. http://www.scribd.com/doc/2909846/Scaling-MySQL-A-Case-Study-of-Hyperic-HQ

    scribd 上的文档大部分可以下载,也可以在线观看,很好的文档分享站点.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章