基于内存的关系数据库memsql初探

database

  1. 背景

    1. 广告系统中,算法模型预估需要根据广告的实时转化统计结果,才能做出更精准的预估;同时,支持多维度聚合查询(例如按照广告各个不同层级维度,按照时间不同粒度的维度),并跨大区合并。一开始的版本是基于mysql,但由于统计数据更新太频繁,异步定期从mysql捞统计结果,导致mysql经常出现活跃连接数太多而频频出现告警。

    2. 尝试过很多优化:

      1. 加数据接入层:中间加一层mysql代理服务data access,缓存mysql的统计结果,所有的读请求都从data access获取,可以减少mysql的读压力(也可以从mysql从库读,减少master节点压力,只是没去尝试)

      2. 减少数据量:删除历史的统计数据,只保留业务需要的时间窗口的统计结果

      3. 减少代理的访问频率:即使加了代理(2个节点),但由于mysql需要同步的表数量太多(接近200个),每个表的数据也达到了百万级别,频繁访问也还是会增加mysql的负担,后面不得已采取牺牲统计的时效性,降低对mysql的访问频率

      4. 加入redis作为统计写入的缓存队列:前面提到的基本都是针对读的优化,实时统计的写入量很大,如果没有先聚合,拿到一条就写入一次,一样会导致mysql负载过高。所以在服务中先聚合后再写入,但是,由于聚合是在内存的,要是服务上线重启,临时聚合的数据来不及写入mysql,又会导致数据丢失。。所以采取了写入redis的方式,redis作为缓存队列,保存一天内具体到每一分钟的统计结果,统计程序定期的从redis中捞取结果,再聚合到5分钟,1个小时,1天,1周的维度。可能这里有人会问,为什么不用kafka或者其他主流mq作为缓存队列,由于需要从其他大区把数据捞出来聚合后一起做统计,这个过程可能会由于物理距离原因而超时,导致统计不准,把消费事务设置为 Exactly Once,跨区消费完了后需要发送确认消息,这个延迟比较大。而且,即使能在一次统计中统计正确,但如果前面有其他的统计出现错误,会导致当天的统计一直错下去,没法补数据。如果用redis,只要数据未过期,可以对之前统计的结果重新统计后覆盖,虽然会牺牲一点redis的qps,但redis支持的qps能达到15w,本身性能就很好,所以不是什么大问题。结果就变成了定期的的insert into xx on duplicate xx

    3. 结果

      1. 一系列优化之后,mysql不再告警了,然而,维护的复杂度也变高了,如果需要增加一个维度,redis、data access、上层应用服务都要改一遍,改起来相当麻烦,而且,维度多,也会导致统计的压力变大。

    4. 主角出场

      1. 这阵子在看《数据密集型应用系统设计》,作者是少有的从工业界干到学术界的牛人,书中提到了基于内存的关系数据库memsql,因此做了简单的调研。

  2. memsql简介

    1. 基于内存,宣称是世界上最快的关系数据库,为了避免服务重启后丢数据,数据定期写磁盘,这点类似redis
    2. 支持横向和纵向扩展:纵向使得单机性能更好,横向支持水平扩展
    3. sql解析:sql预编译到C++中,这就要求sql语句不要经常变化,好处就是常用的语句少了解析部分,执行会比较快
    4. ACID:不是full ACID,A:只对单条语句;I:只支持read commited;D:不是每个事务都持久化。C是目标,AID有缺陷,C也在某种程度下不能完全达到

    5. 性能:官方有做测评,但被一个facebook的员工吐槽了(https://dom.as/2012/06/26/memsql-rage/,知乎有人对观点做了总结:https://zhuanlan.zhihu.com/p/49159963),大概意思就是拿mysql和memsql的不对等的参数做基准测试对比,没有意义。例如:

      1. mysql可以设置 innodb_buffer_pool_size大小,如果设置太小,会导致缓存命中率变低。

      2. mysql设置事务落磁盘的频率: innodb_flush_log_at_trx_commit,频率太高也会影响性能

      3. 最坑的是:由于memsql是以skiplist存的,如果要order by获取pk最大的元素(定义表是asc),则需要排序,这在mysql中不需要排序。不过,这个问题貌似后来已经修复了(见知乎的评论:)

    6. 高可用:支持双机备份

    7. 有人说,如果把mysql的表的存储引擎设置为memory,而且设置触发器写磁盘,不就可以代替memsql了吗?于是有人正对innodb、memory、memsql的性能做了测评,请看以下的测评报告。

    8. 性能测评:

      1. 直接说结论:在增删改查都执行的情况下,qps分别是:

        数据库/引擎

        mysql innodb

        mysql memory

        memsql

        qps

        750

        10k

        50k

        如果仅仅是追求性能,牺牲部分ACID特性,还是可以试试。

      2. 测评过程录制成youtube视频:https://youtu.be/zKh8CsgF1OQ

    9. 但是,这玩意不开源,只有受限制的开发版本(集群总内存不能超过128G)和全功能的商业版本,不开源的情况下,如果使用的不够普遍,而且对其原理不了解的情况下,在生产环境还是不太敢使用。

  3. memsql体验

    1. docker镜像启动:https://github.com/memsql/memsql-docker-quickstart

    2. docker镜像自带基准测试,在开10个并发的情况下,写入qps可以达到140w(当然这个基准测试也是比较水,表字段只有2个)

  4. 总结

    1. 在满足基本功能的情况下追求性能,memsql确实是不错的选择;但是如果对其原理不了解的情况下,在生产环境使用,容易踩坑。

  5. 其他内存数据库

    1.  VoltDB,也是基于内存的关系数据库,也是有收费的商业版和开源版,java写的,特性待调研。

  6. 相关资料

    1. 知乎总结:https://zhuanlan.zhihu.com/p/49159963

    2. facebook工程师吐槽memsql:https://dom.as/2012/06/26/memsql-rage/

    3.  quora:https://www.quora.com/What-benefits-does-MemSQL-offer-over-running-a-MySQL-database-on-ramdisk

以上是 基于内存的关系数据库memsql初探 的全部内容, 来源链接: utcz.com/z/536199.html

回到顶部