基于内存的关系数据库memsql初探
背景
- 广告系统中,算法模型预估需要根据广告的实时转化统计结果,才能做出更精准的预估;同时,支持多维度聚合查询(例如按照广告各个不同层级维度,按照时间不同粒度的维度),并跨大区合并。一开始的版本是基于mysql,但由于统计数据更新太频繁,异步定期从mysql捞统计结果,导致mysql经常出现活跃连接数太多而频频出现告警。
- 尝试过很多优化:
- 加数据接入层:中间加一层mysql代理服务data access,缓存mysql的统计结果,所有的读请求都从data access获取,可以减少mysql的读压力(也可以从mysql从库读,减少master节点压力,只是没去尝试)
- 减少数据量:删除历史的统计数据,只保留业务需要的时间窗口的统计结果
- 减少代理的访问频率:即使加了代理(2个节点),但由于mysql需要同步的表数量太多(接近200个),每个表的数据也达到了百万级别,频繁访问也还是会增加mysql的负担,后面不得已采取牺牲统计的时效性,降低对mysql的访问频率
- 加入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
- 结果:
- 一系列优化之后,mysql不再告警了,然而,维护的复杂度也变高了,如果需要增加一个维度,redis、data access、上层应用服务都要改一遍,改起来相当麻烦,而且,维度多,也会导致统计的压力变大。
- 主角出场:这阵子在看《数据密集型应用系统设计》,作者是少有的从工业界干到学术界的牛人,书中提到了基于内存的关系数据库memsql,因此做了简单的调研。
memsql简介
- 基于内存,定期写磁盘,避免服务重启后丢数据,类似redis
- ACID:不是full ACID,A:只对单条语句;I:只支持read commited;D:不是每个事务都持久化。C是目标,AID有缺陷,C也在某种程度下不能达到
- 性能:官方有做测评,但被一个facebook的员工吐槽了(https://dom.as/2012/06/26/memsql-rage/,知乎有人对观点做了总结:https://zhuanlan.zhihu.com/p/49159963),大概意思就是拿mysql和memsql的不对等的参数做对比,没有意义。例如:
- mysql可以设置 innodb_buffer_pool_size大小,如果设置太小,会导致缓存命中率变低。
- mysql设置事务落磁盘的频率: innodb_flush_log_at_trx_commit,频率太高也会影响性能
- 最坑的是:由于memsql是以skiplist存的,如果要order by获取pk最大的元素(定义表是asc),则需要排序,这在mysql中不需要排序。不过,这个问题貌似后来已经修复了(见知乎的评论:)
- 高可用:支持分布式部署
- 有人说,如果把mysql的表的存储引擎设置为memory,而且设置触发器写磁盘,不就可以代替memsql了吗?于是有人正对innodb、memory、memsql的性能做了测评,请看以下的测评报告。
- 性能测评:
- 直接说结论:在增删改查都执行的情况下,qps分别是:innodb:750,memory:10k,memsql:50k。如果仅仅是追求性能,牺牲部分ACID特性,还是可以试试。
- 但是,这玩意不开源,只有受限制的开发版本和全功能的商业版本,不开源的情况下,如果使用的不够普遍,而且对其原理不了解的情况下,在生产环境还是不太敢使用。
memsql体验
- docker镜像自带基准测试,在开10个并发的情况下,写入qps可以达到140w(当然这个基准测试也是比较水,表字段只有2个)
总结
- 在满足基本功能的情况下追求性能,memsql确实是不错的选择;但是如果对其原理不了解的情况下,在生产环境使用,容易踩坑。
其他内存数据库
- VoltDB,特性待调研。
相关资料
- facebook工程师吐槽memsql:https://dom.as/2012/06/26/memsql-rage/
基于内存的关系数据库memsql初探的更多相关文章
- RDD:基于内存的集群计算容错抽象(转)
原文:http://shiyanjun.cn/archives/744.html 该论文来自Berkeley实验室,英文标题为:Resilient Distributed Datasets: A Fa ...
- RDD:基于内存的集群计算容错抽象
转载自:http://shiyanjun.cn/archives/744.html 摘要 本文提出了分布式内存抽象的概念--弹性分布式数据集(RDD,Resilient Distributed Dat ...
- Impala基于内存的SQL引擎的详细介绍
一.简介 1.概述 Impala是Cloudera公司推出,提供对HDFS.Hbase数据的高性能.低延迟的交互式SQL查询功能. •基于Hive使用内存计算,兼顾数据仓库.具有实时.批处理.多并发等 ...
- tmpfs:一种基于内存的文件系统
tmpfs是一种基于内存的文件系统, tmpfs有时候使用rm(物理内存),有时候使用swap(磁盘一块区域).根据实际情况进行分配. rm:物理内存.real memery的简称? 真实内存就是电脑 ...
- 高性能、高容错、基于内存的开源分布式存储系统Tachyon的简单介绍
Tachyon是什么? Tachyon是一个高性能.高容错.基于内存的开源分布式存储系统,并具有类Java的文件API.插件式的底层文件系统.兼容Hadoop MapReduce和Apache Spa ...
- 【转】Spark是基于内存的分布式计算引擎
Spark是基于内存的分布式计算引擎,以处理的高效和稳定著称.然而在实际的应用开发过程中,开发者还是会遇到种种问题,其中一大类就是和性能相关.在本文中,笔者将结合自身实践,谈谈如何尽可能地提高应用程序 ...
- java-消息中间件-基于内存的mq
如果用户的请求比较费时,可以考虑将用户的请求信息放到队列中,立即返回给用户处理中等信息,这样可以给用户比较流畅的体验,后端可以利用单独的服务消费消息,做到了解耦,提高了并发能力. 本文使用jdk为我们 ...
- Spark 介绍(基于内存计算的大数据并行计算框架)
Spark 介绍(基于内存计算的大数据并行计算框架) Hadoop与Spark 行业广泛使用Hadoop来分析他们的数据集.原因是Hadoop框架基于一个简单的编程模型(MapReduce),它支持 ...
- 《SPARK/TACHYON:基于内存的分布式存储系统》-史鸣飞(英特尔亚太研发有限公司大数据软件部工程师)
史鸣飞:大家好,我是叫史鸣飞,来自英特尔公司,接下来我向大家介绍一下Tachyon.我事先想了解一下大家有没有听说过Tachyon,或者是对Tachyon有没有一些了解?对Spark呢? 首先做一个介 ...
随机推荐
- List 去重的 6 种方法,这个方法最完美!
在日常的业务开发中,偶尔会遇到需要将 List 集合中的重复数据去除掉的场景.这个时候可能有同学会问:为什么不直接使用 Set 或者 LinkedHashSet 呢?这样不就没有重复数据的问题了嘛? ...
- javaSE高级篇1 — 异常与多线程基础
1.异常的体系结构 注:Throwable是一个类,不是一个接口,这个类里面是描述的一些Error和Exception的共性,如图所示: 异常 / 错误是什么意思? 定义:指的是程序运行过程中,可能 ...
- 零基础学习java------day11------常用API---Object、Scanner、String、StringBufer/StringBuilder
API概述 API(application Programming Interface, 应用程序编程接口),是一些预先定义的函数.目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力, ...
- Gradle入门及SpringBoot项目构建
https://blog.csdn.net/qq_27520051/article/details/90384483 一.介绍 Gradle 是一种构建工具,它抛弃了基于XML的构建脚本,取而代之的是 ...
- ORACEL 创建DIRECTORY
oracle要直接对文件进行读写必须先创建一个DIRECTORY. 语法如下: CREATE DIRECTORY UTL_FILE_DIR AS '/home/oracle/oradir'; 可以通过 ...
- 【Linux】【Basis】文件
refer to: https://en.wikipedia.org/wiki/POSIX refer to: https://en.wikipedia.org/wiki/Unix_file_type ...
- java通过反射获取Java对象属性值
说明: 作为反射工具类,通过对象和属性的名字获取对象属性的值,如果在当前对象属性没有找到,依次向上收集所有父类的属 性,直到找到属性值,没有找到返回null: 代码: 1.classUtil pack ...
- SpringColud微服务-微服务概述
一.什么是微服务架构 微服务架构是一种架构模式,它提倡讲单一应用程序划分为一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.每个服务运行在单独的进程当中,服务与服务之间采用轻量级的通信机制 ...
- C#生成pdf -- iText7 设置自定义字体和表格
itextsharp已经不再更新,由iText 7来替代 安装 nuget 安装 itext7 注册自定义字体 下载字体文件 .ttc或.ttf到项目目录,设置更新则拷贝到输出目录,这样构建的时候会把 ...
- <转>libevent使用demo
这篇文章介绍下libevent在socket异步编程中的应用.在一些对性能要求较高的网络应用程序中,为了防止程序阻塞在socket I/O操作上造成程序性能的下降,需要使用异步编程,即程序准备好读写的 ...