关于存储过程:技术分享-MySQL-的-AWR-Report-MySQL-状态诊断报告

作者:秦福朗 爱可生 DBA 团队成员,负责我的项目日常问题解决及公司平台问题排查。酷爱 IT,喜爱在互联网里畅游,善于摄影、厨艺,不会厨艺的 DBA 不是好司机,didi~ 本文起源:原创投稿 *爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。 引言用过 Oracle 数据库的同学都晓得,在 Oracle 有个性能:AWR(全称为 Automatic Workload Repository),主动负载信息库。它收集对于特定数据库的操作统计信息和其余统计信息,Oracle 以固定的工夫距离(默认为 1 个小时)为其所有重要的统计信息和负载信息执行一次快照,并将快照寄存入 AWR 中,为 DBA 们剖析数据库提供了十分好的便当条件。尽管 MySQL 没有这么强的性能,但 MySQL 有一个相似的,名叫 diagnostics 的存储过程,提供了相相似的性能。 diagnostics() 存储过程是利用 MySQL 本身的 information_schema,performance_schema、sys 等元数据信息及性能数据信息的库表函数等,对以后服务器状态进行诊断,提供给 DBA 一份能够用于剖析数据库状态的报告。 根本蕴含信息diagnostics() 收集的数据次要蕴含以下信息: 来自 metrics 视图的信息;来自其余相干的 sys schema 视图的信息,比方检测第 95 百分位数的查问视图;如果是 NDB Cluster 的 MySQL 服务器,则还会有 ndbinfo schema 的信息;主从复制状态信息一些 sys schema 的视图被计算为初始(可选)、overall 和 delta: 初始视图是 diagnostics() 过程开始时的视图内容。这个输入与用于 delta 视图的起始值雷同。如果 diagnostics.include_raw 配置选项为 ON,则初始视图会被蕴含在报告中。overall 视图是 diagnostics() 过程完结时的视图内容。这个输入与用于 delta 视图的完结值雷同。overall 视图总是被蕴含在报告内。delta 视图是 procedure 执行开始到完结的差别。最小值和最大值别离是完结视图的最小值和最大值。它们不肯定反映监控期间的最小值和最大值。除了 metrics 视图外,Delta 仅计算第一个和最初一个输入之间的差值。留神: ...

May 7, 2021 · 2 min · jiezi

关于存储过程:理论研究漫谈传统IT基础设施09存储03

本文欢送转载,转载请注明出处和作者。 存储类型如同后面所讲的服务器一样,存储也有很多不同维度的比照。例如块存储、ISCSI、SAN,平时可能会听到不懂行的人拿这几个来比照,然而这基本不是一个维度下面的概念,根本无法进行比照。以下咱们从几个维度来对存储类型进行比照。 1-依照存储的连贯形式 DAS:特色:磁盘装在服务器外部,直连服务器的串行(SCSI)接口。(相似笔记本通过USB直接插入移动硬盘) 长处:部署简略,即插即用,价格便宜; 毛病:只能单台设施应用,无奈共享。 NAS:特点:磁盘阵列接入IP交换机,服务器通过IP网络拜访存储;(相似Windows笔记本,文件夹右键属性创立共享文件夹,而后其余客户端能够通过\IP共享文件夹名称拜访) 长处:磁盘阵列能够通过IP网络多台服务器共享拜访,便宜; 毛病:传输数据速率较慢,对大量读写IO的反对较差。 SAN:特点:磁盘阵列接入光纤交换机,服务器配置HBA卡接入光纤交换机拜访存储。 长处:三者外面性能最优,IO读写性能最好,速度最快; 毛病:价格较高,须要额定购买光纤交换机与HBA卡进行组网。 2-依照封装协定分类SCSI协定:对应DAS存储,硬盘通过IDE或SATA接口线连贯服务器主板,数据通过SCSI协定进行封装,而后传输。 ISCSI协定(对应IPSAN网络):对应NAS或是应用IP交换机的块存储,磁盘阵列设施有控制器,控制器上有NAS接口板(相当于以太网卡),通过以太网线与一般IP交换机互联,数据先通过SCSI协定封装,外层再封装IP协定,再通过IP网络传输。 FC协定(对应SAN网络):对应SAN网络的存储(个别为块存储),磁盘阵列设施有控制器,控制器有光纤接口,通过光纤与光纤交换机互联,服务器须要特地配置HBA卡,连贯光纤交换机拜访磁盘阵列,数据通过FC协定进行封装。 FCOE协定:对应SAN网络存储,但IP交换机采纳具备FCoE性能的交换机,数据通过FC协定进行封装,外层再封装IP协定,再通过IP网络传输。 3-依照存储网络分类 4-按产品类型分类1、集中式存储集中式存储指采纳单台/单套专用存储硬件,对数据进行集中寄存,而后通过接入FC/IP网络的形式,共享给多台服务器同时拜访的存储。此类存储的冗余通常通过该专用硬件外面各局部部件进行冗余配置来解决(如通常配置至多2个控制器,磁盘须要配置热备盘,磁盘组要做Raid,风扇、电源也冗余配置等)。(如IBM DS8000、EMC VMAX零碎列 等) 长处是专用硬件,各局部部件冗余,性能强劲,能够通过减少扩大柜与磁盘扩容容量与性能。(Scale Up) 毛病是专用硬件价格昂贵,并且通常品牌绑定,不同品牌之间的设施无奈搭配扩容容量应用。甚至同品牌的不同系列存储产品,都不会向下兼容。而就算再高端的系列产品,受限于控制器的性能,上面能够带的磁盘总数与扩大柜数,都是有限度的。因而一旦应用容量/性能超过最大值,就要弄一套新的存储,须要业务那边思考如何将数据拆分到2套独立的存储中去。 集中式存储次要分以下两类: 01、传统块存储:根本对应SAN、IPSAN、DAS,指裸磁盘映射给服务器的操作系统,由操作系统对裸磁盘进行格式化(即装置文件系统)后能力应用。 长处是读写IO性能高,局部数据库必须采纳这种形式的存储。毛病是不适宜存储数据的共享,如Linux服务器的磁盘文件系统是EXT4,而Windows的服务器文件系统为NTFS,两者的磁盘数据无奈共享。 02、传统文件存储:根本对应NAS存储,用一般服务器也能作为NAS应用,有专门的文件系统(NFS、CIFS),其余服务器只有IP可达,即能够应用其作为文件存储,拜访的时候能看见一级级的文件目录,无需格式化即可以上传或下载文件。 长处是能够共享数据(Linux/Win的服务器都能拜访),毛病是只适宜寄存文件(数据库不能用这种)以及IO性能差。 2、分布式存储能够了解为服务器+DAS+软件:业界根本采纳服务器装大硬盘,而后分布式部署,再通过几台治理服务器装置对象存储软件的形式实现。治理服务器有所有数据的元数据(即所有数据的属性,如大小,日期等),用户拜访时先向治理服务器查问数据所在,而后间接拜访理论存储数据的分布式对象存储服务器拿数据。 长处是分布式的服务器同时并行对外提供服务,晋升了IO性能,实践上能够有限横向扩大。(Scale Out) 毛病是依赖于软件自身,操作、保护都有门槛,须要专门的技术人员去治理与运维。 分布式存储别离有分布式块存储、分布式文件存储、分布式对象存储。 对象存储:对象存储适宜寄存一次上传,屡次读取,从不批改的数据。(例如当初挪动互联网,大家抖音发的视频,微博、朋友圈发的文字、图片、视频,都有此属性)对象一旦上传是不能批改的。 对象存储与传统的存储不太一样,寄存的货色叫对象。对象除了须要存储的数据自身,还包含一部分叫元数据的内容(用来形容数据自身属性的数据,例如最初批改工夫,对象大小等)。对象寄存在一个叫Bucket的存储空间下,没有文件系统、目录等概念,存储空间在对象存储内有惟一的全局ID,存储对象数据是通过KEY:VALUE的键值对的形式进行存储的。用户能够间接通过“存储空间对象KEY”的形式,通过网络读取与调用对象的VALUE。 与块存储与文件存储相比: 1、文件存储是树状索引式的,拜访越深刻的目录,耗费的资源越大。对象存储应用key:value进行存储,读取开销很低。 2、块存储不不便进行数据共享,而文件存储能够将文件上传之后,其余用户有拜访权限的状况下能够间接通过http/RestAPI等形式调用对象,从而达到数据共享。 3、NOSQL存储nosql的全称是not-only-sql,以往罕用的数据库都是关系型数据库,将业务逻辑通过抽象化的形式,具象成一堆具备关联关系的二维表,然而随着挪动互联网的高速倒退传统的关系型数据库在应酬超大规模超大流量以及高并发的时候力不从心,特地是在SNS之类的利用,很多都是图片、视频等非结构化的数据。 NOSQL具备Key-Value存储、列式存储、对象存储等多种形式,在特定的利用场景可能提供更快的查问能力。更多精彩内容,能够关注我的微信公众号:Waiting的运维日常本篇文章由一文多发平台ArtiPub主动公布

October 17, 2020 · 1 min · jiezi

关于存储过程:理论研究漫谈传统IT基础设施07存储01

本文欢送转载,转载请注明出处和作者。存储是个很大的话题,而且讲起来比拟硬核,很多术语与知识点。咱们尽量每一部分都标注重点,以及类比了解。 存储是什么 存储的外围是硬盘中的磁片。(一个硬盘有很多块) 磁盘外面由多个铝合金资料做的碟片形成,用于存储数据。每个碟片会有一个读写磁头通过磁化碟片来存储数据。 碟片在格式化被划分成为许多同心圆,这些同心圆的轨迹叫做磁道。磁道从最外圈向最内圈由0开始编号。 碟片上的每个磁道被等分为若干个弧段,这些弧段便是磁盘的扇区。每个扇区512个字节,扇区是磁盘可分的最小单位。 所有盘面上的同一磁道,垂直方向上形成一个圆柱,叫做柱面。 为缩小寻道工夫,磁头读写数据时先从同一个柱面的磁道0开始操作,而后再去往下一个柱面。 因为每个扇区的长度相等,因而0磁道周长最长,扇区最多,且各磁道角速度相等,因而外层磁道比内层磁道读写速率要高。 (重点:记住“扇区(sector)是磁盘可分的最小单位”即可,其余“柱面”、“磁道”那些前面都用不上) 如何应用磁盘第一步:对磁盘进行格式化:未格式化的硬盘称作裸磁盘,不能被操作系统辨认或间接应用。 格式化操作将裸磁盘划分为多个磁道,并且将多个扇区组成一个文件块(Block),块是操作系统可能辨认与操作的最小单位。(FAT32最小块1KB,最大为4GB,NTFS最小块4KB,最大64GB)。 格式化操作其外延是为了将磁盘空间依照文件系统可能辨认的办法进行编址,以便文件系统进行读写操作。而不同的操作系统可能反对不同的文件系统。 为啥要编址呢,其实磁盘就像住房,如果你只有一套房,并且是自住的,那么爱咋咋滴,反正就你本人住。然而如果你有N套房,你当房东了,那么有租客过去了,一手交钱、一手交房卡,那么租客如何找到他的房间而不要敲错他人房间的门呢?房东你是不是要通知租客他租的房间就是几零几号房?那么其实这个几零几的编号,就是你对房间进行了编址。 其实磁盘也就一样,裸磁盘相当于超市/图书馆门口那些长期储物柜,每个扇区相当于1个储物柜,而操作系统相当于长期存放管理员,应用程序相当于带着行李的游客。应用程序(游客)往裸磁盘(存储柜)存入货色的时候,租客不是间接轻易找个储物柜硬塞的,而是到寄存处,把行李交给管理员,而管理员看看哪里有空的柜子,而后把行李存进去,而后把带有存物柜编号(编址后,多个扇区组成的文件系统块地址)的钥匙/凭证交给游客。等应用程序调用数据(游客取行李)的时候,管理员依据凭证(编址),从对应的存物柜外面提取行李(数据)提取进去,而后交给游客。 (重点:记住1、“格式化就是对裸磁盘空间进行编地址”,2、“文件块(Block),块是操作系统可能辨认与操作的最小单位”) 第二步:对磁盘进行分区分区其实就是指定每个分区由哪个扇区开始,到那个扇区完结。 分区能够使多个分区之间的数据进行隔离。 分区后各分区能够用于格式化不同的文件系统,并且每个分区的格式化操作不会影响另外一个分区。(如平时C盘重装WINDOWS操作系统,不会影响D、E盘数据,数据不会清空) 第一个扇区次要存储:(1)次要开机区(Master boot record, MBR)及宰割表(partition table), 其中 MBR 占有 446 bytes,而 partition table 则占有 64 bytes。 硬盘最多划分4个物理分区(主分区/扩大分区),须要更多的分区就要在扩大分区下面划逻辑分区。 数据如何写入存储一般文件系统以FAT32文件系统为例,对硬盘进行格式化后,多个扇区组成了多个块,并且对块进行了编址(下图每个矩形为1个文件块)。 假如每个块为1KB,一份4KB大小的文件,被分为4个文件块,别离存储到块1、4、7、15中去。 如1、4、7、15文件块各位于不同的磁片,那么每个磁片的磁头会参加到读取数据的操作中去。 这种形式读写效率低,如1、4、7文件块都在第一块磁盘,原本磁盘转一圈即可读取完3个文件块,然而因为1前面指向7,所以转第一圈通过4时不会读取,读取7后才晓得要读取4,须要转第二圈才可能读取到4文件块。 索引式文件系统Linux的EXT4为索引式文件系统,磁盘格式化后会生成Inode与Block,其中Block用户存储文件数据,Inode用来寄存文件的元数据。每个文件有惟一的Inode编号。当拜访文件时,会在Inode查找对应编号,找到元数据后,就一次过晓得文件分块所有的寄存地位,这个时候磁盘转一圈就能够全副数据读取结束了。因而读写效率较高。 日志式文件系统传统的文件系统,如果在写入过程产生中断,会产生写入设施与被写入设施上的数据不统一的问题,将须要启动数据修复,修复工夫长,资源耗费大,所以呈现了日志式文件系统。 在每次写入数据之前,会先在日志记录缓存区中写下要进行的写入的数据的信息,而后才会着手将数据以及元数据写入到磁盘中,写入数据实现后,又会将日志记录缓存区块中的记录写入到磁盘的日志记录区,这样如果中途呈现问题,查看日志记录缓存区/日志记录区,就能找到中断的地位或者谬误的起因,从新进行读写,排错工夫短,修复工夫快。 更多精彩内容,能够关注我的微信公众号:Waiting的运维日常本篇文章由一文多发平台ArtiPub主动公布

October 17, 2020 · 1 min · jiezi

为什么-K8s-集群达万级规模阿里购物体验还能如丝顺滑

阿里妹导读:本文主要介绍阿里巴巴和蚂蚁金服在大规模生产环境中落地 Kubernetes 的过程中,在集群规模上遇到的典型问题以及对应的解决方案,内容包含对 etcd、kube-apiserver、kube-controller 的若干性能及稳定性增强,这些关键的增强是阿里巴巴和蚂蚁金服内部上万节点的 Kubernetes 集群能够平稳支撑 2019 年天猫 618 大促的关键所在。文内藏福利,向下滑滑滑,免费课程立刻领取~背景从阿里巴巴最早期的 AI 系统(2013)开始,集群管理系统经历了多轮的架构演进,到 2018 年全面的应用 Kubernetes ,这期间的故事是非常精彩的。这里忽略系统演进的过程,不去讨论为什么 Kubernetes 能够在社区和公司内部全面的胜出,而是将焦点关注到应用 Kubernetes 中会遇到什么样的问题,以及我们做了哪些关键的优化。 在阿里巴巴和蚂蚁金服的生产环境中,容器化的应用超过了 10k 个,全网的容器在百万的级别,运行在十几万台宿主机上。支撑阿里巴巴核心电商业务的集群有十几个,最大的集群有几万的节点。在落地 Kubernetes 的过程中,在规模上面临了很大的挑战,比如如何将 Kubernetes 应用到超大规模的生产级别。 罗马不是一天就建成的,为了了解 Kubernetes 的性能瓶颈,我们结合阿里和蚂蚁的生产集群现状,估算了在 10k 个节点的集群中,预计会达到的规模: 20w pods100w objects 我们基于 Kubemark 搭建了大规模集群模拟的平台,通过一个容器启动多个(50个)Kubemark 进程的方式,使用了 200 个 4c 的容器模拟了 10k 节点的 kubelet。在模拟集群中运行常见的负载时,我们发现一些基本的操作比如 Pod 调度延迟非常高,达到了惊人的 10s 这一级别,并且集群处在非常不稳定的状态。 当 Kubernetes 集群规模达到 10k 节点时,系统的各个组件均出现相应的性能问题,比如: etcd 中出现了大量的读写延迟,并且产生了拒绝服务的情形,同时因其空间的限制也无法承载 Kubernetes 存储大量的对象;API Server 查询 pods/nodes 延迟非常的高,并发查询请求可能地址后端 etcd oom;Controller 不能及时从 API Server 感知到在最新的变化,处理的延时较高;当发生异常重启时,服务的恢复时间需要几分钟;Scheduler 延迟高、吞吐低,无法适应阿里业务日常运维的需求,更无法支持大促态的极端场景。etcd improvements为了解决这些问题,阿里云容器平台在各方面都做了很大的努力,改进 Kubernetes 在大规模场景下的性能。 ...

October 17, 2019 · 5 min · jiezi

Timestream开发最佳实践

背景Timestream模型是针对时序场景设计的特有模型,可以让用户快速完成业务代码的开发,实现相关业务需求。但是,如果业务系统不仅想实现基础的相关业务功能,还要达到最佳的性能,并且兼顾到未来的扩展性的话,就不是一件特别容易的事情。 本文会以共享汽车管理平台为例,介绍一系列的timestream最佳设计和使用,给业务设计和使用提供一些参考。关于共享汽车管理平台的场景,细节请参考:《基于Tablestore的共享汽车管理平台》。 场景和模型简介 在共享汽车管理平台这个场景中,主要是对车辆的状态轨迹监控、车俩元数据以及订单元数据进行管理。另外,还会对相关的数据进行计算分析并存储相关结果: 车辆状态轨迹:记录了车辆的状态监控,比如车速、位置、续航等数据,另外还需要记录车辆行驶过程中的违章记录,比如:是否超速、是否闯红灯等等;车辆元数据:记录车辆的基本属性信息,便于用户进行车辆检索,比如:车型、车牌、颜色等;订单元数据:订单相关信息记录,包含行程的起止时间、车辆、用户、费用等信息业务主要是对上面三部分数据进行查询和检索,满足业务场景的需求。其中车辆元数据以及状态轨迹数据是典型的时序序列,可以很方便的映射到Timestream模型中。 下图是数据模型的映射: 下面介绍一下模型设计的细节以及设计中需要注意的一些优化点,这些优化点对于业务功能以及性能上都有一定的提升。 业务模型设计在Timestream模型中,主要包含了元数据和数据点两部分数据,分别使用一个元数据表以及若干个数据表进行存储。下面介绍这两类数据在存储设计的关键点。 元数据表设计在共享汽车这个场景下,元数据表主要存储两类数据:车辆的基本信息、车辆的最近状态数据(位置、续航、状态、违章统计等),业务会根据各类信息进行多条件的组合查询符合条件的车辆。 如上图所示,Timestream的元数据表会通过多元索引来提供丰富的数据检索能力。在Timestream模型的元数据中,包含了name、tags、attributes三类数据,其中name、tags默认会提供数据检索能力,attributes则需要在创建Meta表的时候指定需要索引的attributes字段以及相关信息,默认attributes并不支持检索。需要注意的是,目前并不支持动态修改Meta表的索引字段,所以最好能在设计之初能够考虑到当前以及未来的功能需求,下面介绍一下相关信息是如何映射到模型以及相关的设计。 name设计name字段的选取是很关键的,是数据检索性能的一个重要影响因素,不同的name字段设计可能会导致查询延时相差一个数量级。name字段的选取建议满足以下条件: 绝大多数查询场景都会对该字段进行精确查询该字段单个取值下的最大记录数不宜过多,比如说不超过一千万条记录在共享汽车管理平台这个场景下,管理的是各个平台的车辆,而在车辆检索的时候,一定会指定的条件是平台的名字,并且某个平台的车辆其实也不会太多,一般也就百万量级,所以这里可以将平台作为name。 tags设计在Timestream模型中,Name和Tags可以唯一确定某个元数据,在这个场景中,唯一确定某辆车的信息是:平台、车辆ID,其中平台是name,所以,tags中只需要存储ID即可。tags设计需要注意: tags的总长度尽可能的短,只把唯一确定主体的信息放到tag中,其余信息均放到attributes中tag只支持string类型的数据,如果业务字段是数值类型,需要将其转成string进行存储attributes设计attributes是主体的可变属性,也可以用来存储主体的非唯一属性。在这个场景中,车辆的基本信息以及当前状态都是用attributes来进行存储。attributes设计关键点: 创建meta表的时候需要指定有检索需求的attributes以及相关属性,默认attributes是不支持索引的数值型数据尽可能使用int来存储,attribute支持多类型的数据,但在数据检索过程中,int类型的数据检索效率比string类型高的多,建议使用int,索引类型为LONG考虑未来系统的扩展性,可以预留一列作为扩展字段,索引类型为KEYWORD,并且是Array索引创建示例代码: public void createMetaTable() { db.createMetaTable(Arrays.asList( new AttributeIndexSchema("地区", AttributeIndexSchema.Type.KEYWORD), ... // 数值类型索引 new AttributeIndexSchema("座位", AttributeIndexSchema.Type.LONG), ... // 扩展字段,数组类型索引 new AttributeIndexSchema("配置1", AttributeIndexSchema.Type.KEYWORD).isArray() ));数据表设计Timestream可以支持多个数据表的存储,来满足不同的业务场景需求。另外,为了能够利用底层引擎所做的性能优化,我们推荐append的写入方式,即不会对已有数据进行修改,所以在以下场景中,我们建议业务将数据分到不同数据表中进行存储: 数据精度不同,特别是在监控场景下,这个需求更加突出。按数据精度分表便于后续数据的查询,如果查询长周期的数据可以去查询低精度的表,减少查询的数据量,提高查询效率需要对数据进行加工处理,也就是会对数据进行更新,建议将处理之后的数据写到另外一张表中在共享汽车这个场景中,需要对车辆的状态轨迹数据进行流式处理,比如检测是否超速等违章、车辆状态轨迹是否异常等,然后将处理之后的数据写到另外一张表中,提供给业务进行查询。 sdk使用前面介绍了业务模型设计需要注意的地方,对业务功能拓展能力以及性能都有一定的提升。下面介绍一下timestream sdk使用的一些性能优化点。 数据写入元数据元数据写入支持两种方式:put和update。其中put会删除老的记录,并且插入一个全新行;update则是对原有记录的部分attributes进行更新。建议尽量使用Put的方式进行写入。示例代码: public void writeMeta() { TimestreamIdentifier identifier = new TimestreamIdentifier.Builder("*滴") .addTag("ID", carNo) .build(); TimestreamMeta meta = new TimestreamMeta(identifier) .addAttribute("地区", "杭州") .addAttribute("座位", 4) ... .addAttribute("状态", "闲置"); // 插入车辆信息 metaWriter.put(meta);}数据点数据点写入也提供了两种方式:同步和异步。其中异步接口底层是通过TableStoreWriter进行异步写入,其写入吞吐能力更高,对写入延时不是特别敏感的业务建议使用异步方式。示例代码: ...

August 28, 2019 · 1 min · jiezi

阿里云-ESSD-采用自研新一代存储网络协议打造超级高速

8月26日,阿里云透露,正投入自研数据存储“超级高速”,核心存储产品ESSD已率先采用这一最新的自研存储网络协议,并实现大规模商用,数据传输效率提高50%。 据了解,未来该协议还将继续演进,有望取代传统TCP网络协议。此前,谷歌、微软也曾先后发表论文试图突破瓶颈,但都未大规模应用。 随着AIoT时代的到来,所有数据都要求实时采集、传输、计算,传统 TCP 和 RDMA 网络都无法完美适配云时代的存储需求。 ESSD是业内首个百万级 IOPS 、百微秒延时云存储产品,相当于一个千万平米的巨型数据仓库,自带时速超过120公里的超级高速,仅需1秒就可以完成1部高清电影的传输和存储。 其优异的性能得益于阿里云的多项技术自研,底层架构基于自研大规模分布式存储系统盘古 2.0,存储芯片采用自研Aliflash SSD,并且依托自研网络协议 Luna 和增强型RDMA 数据传输协议,结合自研HPCC流控算法,深度优化TCP,大幅降低计算资源消耗及响应延时,使ESSD的数据传输效率可提高50%。 采用全新网络协议的ESSD已正式商用,目前服务数万企业,涵盖自动驾驶、工业物联网、AR/VR、证券交易、电商搜索等数据高并发领域。 “ESSD为企业数据存储和业务敏捷创新提供了新的可能,成为AIoT海量数据存储场景的标配。”阿里云智能存储产品资深总监Alex Chen表示。 阿里云拥有全球最丰富的云存储产品家族,总数据存储量达数十EB,凭借多层次防护、跨区域容灾等能力连续三年入选Gartner全球云存储魔力象限,并且被列为全球领导者地位。 本文作者:阿里云头条阅读原文 本文为云栖社区原创内容,未经允许不得转载。

August 27, 2019 · 1 min · jiezi

DLedger-基于-raft-协议的-commitlog-存储库

“点击获取上云帮助文档” 尊敬的阿里云用户: 您好!为方便您试用开源 RocketMQ 客户端访问阿里云MQ,我们申请了专门的优惠券,优惠券可以直接抵扣金额。请填写下您公司账号信息,点击上图,了解更多哦。 一、DLedger引入目的 在 RocketMQ 4.5 版本之前,RocketMQ 只有 Master/Slave 一种部署方式,一组 broker 中有一个 Master ,有零到多个 Slave,Slave 通过同步复制或异步复制的方式去同步 Master 数据。Master/Slave 部署模式,提供了一定的高可用性。 但这样的部署模式,有一定缺陷。比如故障转移方面,如果主节点挂了,还需要人为手动进行重启或者切换,无法自动将一个从节点转换为主节点。因此,我们希望能有一个新的多副本架构,去解决这个问题。 新的多副本架构首先需要解决自动故障转移的问题,本质上来说是自动选主的问题。这个问题的解决方案基本可以分为两种: 利用第三方协调服务集群完成选主,比如 zookeeper 或者 etcd。这种方案会引入了重量级外部组件,加重部署,运维和故障诊断成本,比如在维护 RocketMQ 集群还需要维护 zookeeper 集群,并且 zookeeper 集群故障会影响到 RocketMQ 集群。利用 raft 协议来完成一个自动选主,raft 协议相比前者的优点是不需要引入外部组件,自动选主逻辑集成到各个节点的进程中,节点之间通过通信就可以完成选主。因此最后选择用 raft 协议来解决这个问题,而 DLedger 就是一个基于 raft 协议的 commitlog 存储库,也是 RocketMQ 实现新的高可用多副本架构的关键。 二、DLedger 设计理念1. DLedger 定位 Raft 协议是复制状态机的实现,这种模型应用到消息系统中就会存在问题。对于消息系统来说,它本身是一个中间代理,commitlog 状态是系统最终状态,并不需要状态机再去完成一次状态构建。因此 DLedger 去掉了 raft 协议中状态机的部分,但基于raft协议保证commitlog 是一致的,并且是高可用的。 另一方面 DLedger 又是一个轻量级的 java library。它对外提供的 API 非常简单,append 和 get。Append 向 DLedger 添加数据,并且添加的数据会对应一个递增的索引,而 get 可以根据索引去获得相应的数据。因此 DLedger 是一个 append only 的日志系统。 ...

August 8, 2019 · 2 min · jiezi

长脸了阿里云这位英雄拿下了世界第一

阿里云数据库又被顶级机构点名了! 近日,全球最知名的数据管理系统评测标准化TPC组织公布了数据库领域分析性能基准测试最新排名,阿里云超大规模分析型数据库AnalyticDB登上榜首,是全球首个通过TPC严格审计认证的云数据库产品。 简单来说,AnalyticDB是一款可以对数据进行在线统计和分析的数据库,帮助企业简单快速实时挖掘数据价值。登上TPC榜首,意味着其已经成为全球最快的实时数据仓库! 目前,阿里云已经拥有国内最丰富的云数据库产品,AnalyticDB只是其中之一。 在多个数据库细分领域,阿里云已经实现了业界领先,并且已经集齐了一套最强阵容: 01在新零售场景中,数据分析师做市场趋势分析、业务在做广告投放时,都需要在PB级数据上依据不断变化的业务模型做分析探索,对业务发展方向进行决策。 而这就需要分析型数据库AnalyticDB的能力了,目前这款产品已经成为全球最快的实时数据仓库,在复杂分析场景中性能提升10倍,万亿数据多维分析仅需毫秒级。 02例如面对互联网大规模流量场景,阿里云拥有国内首款云原生数据库POLARDB,它最大的特点就是拥有极强的弹性能力,能大能小,解决了传统数据库昂贵、扩展性差、技术复杂、迭代慢的瓶颈。 技术方面,也采用了多个领先技术:容器虚拟化技术、存储与计算分离、共享分布式块存储技术,企业只需5分钟即可实现缩扩容,计算能力最高可扩展至1000核,存储容量最高可达100TB。被认为是云时代企业数据库的最佳选择。 03还有一类是擅长多度关系数据查询的。在金融欺诈检测场景中,图数据库可快速通过贷款联系人(或者联系人的联系人)信用信息,对用户进行信用评分,如果评分较低,则拒绝贷款或者提升利率。 阿里云GDB就具备这样的能力,GDB是国内首个云原生图数据库,可以对高度互连的数据集进行深度优化,用最短代码实现多度关系数据的查询与存储,提升查询效率10倍以上,查询时间降低至毫秒级。 04作为阿里云最早的云数据库产品,RDS已经成长为业界功能最丰富的数据库,支持MySQL、SQL Server、PostgreSQL 、MariaDB等主流数据库,可以满足不同场景的需求。 05传统数据库要上云,最关键的一步是保障数据库高效可靠地迁移。因为数据库承载着企业核心业务,但传统的数据库迁移工具要求数据库在迁移中必须停服,极大影响业务。 阿里云数据传输服务DTS大幅提升了数据库上云的速度,其最大的特点是采用分布式并发架构、智能分片、并行抓取技术,数据迁移最快可达100Mb/S,支持18种数据源,百PB级数据迁移业界最快。 大家不妨脑洞一下,看完这五款数据库产品,你想到了什么超级英雄? 本文作者:阿里云头条阅读原文 本文为云栖社区原创内容,未经允许不得转载。

July 16, 2019 · 1 min · jiezi

数据湖正在成为新的数据仓库

编译:诚历,阿里巴巴计算平台事业部 EMR 技术专家,Apache Sentry PMC,Apache Commons Committer,目前从事开源大数据存储和优化方面的工作。 像公有云数据湖和 Delta Lake 这样的平台指出了一个中央数据枢纽的趋势,用来支持决策和AI驱动的自动化决策。 数据仓库是否再次加入这股浪潮呢,或者会逐渐消亡? 如果你不清楚这个问题的答案也很正常。数据仓库在一方面目前仍处于热门阶段。笔者作为一个长期的行业观察者,看到了在不断创新和创业活动浪潮下行业的快速发展。 这种趋势基本上始于十年前标准设备进入数据仓库主流,然后随着市场向新一代云数仓转移逐渐获得了新动力。在过去几年中,一个云数仓供应商(Snowflake) 在市场上获得了非常多的支持。 数据仓库的衰落但在另一方面,数据仓库也不断被行业中的新事物所冲击,例如大数据、机器学习和人工智能。这种趋势造成了数据仓库在企业IT优先级下降的印象,但事实上大多数组织至少有一个或者多个数据仓库服务于各种下游应用程序。 数据仓库一直作为企业核心工作服务,是几年前我觉得数据仓库远未消亡的原因,这也可能解释了为什么其他观察者认为他们必须重新定义数据仓库的概念,以使其在数据湖和云计算时代保持相关性。 数据仓库作为一种实践,不仅蓬勃发展,而且现在已被视为云计算行业的重要核心增长。但是,如果你只是关注以此数据仓库标签进入市场的那些平台(例如Snowflake),你也将错过这个领域大部分的动作。 数据湖的兴起许多人认为“数据湖”正在迅速发展成为下一代数据仓库。对于那些不熟悉这个概念的人来说,数据湖是多结构数据的系统或存储库,它们以原始格式和模式存储,通常作为对象“blob”或文件存储。 数据湖通常用作所有企业数据的单个存储,包括源系统数据的原始副本和用于生成报告,可视化,数据分析和机器学习等任务的转换数据。它们包含分布式文件或对象存储,机器学习模型库以及高度并行化的处理和存储资源集群。并且,数据库通常在读取时使用模式,并使用统计模型从中提取有意义的相关性和模式,而不是对它们存储的对象强制执行通用模式和语义。 这些都与Inmon和Kimball核心概念不一致,这些概念为大多数专业人员的数据仓库方法提供了信息。从根本上说,一个数据仓库主要用来聚合,保留和管理官方认可的“单一版本的真实”数据记录。此概念与所管理数据的特定应用程序域以及使用它的特定用例无关。 如果你怀疑我在那个分数上说的话,请看看Bill Inmon对数据仓库的定义以及Inmon和Ralph Kimball框架的比较。数据仓库通常都是关于数据驱动的决策支持,这使得它可以很好地扩展到AI驱动的推理的新世界。 下一代数据仓库在过去的一年中,一些备受瞩目的行业公告标志着数据仓库角色的转变。尽管决策支持(也称为商业智能,报告和在线分析处理)仍然是大多数数据仓库的核心用例,但我们看到了其向决策自动化的稳步转变。换句话说,数据仓库现在正支持着数据科学管道,为数据驱动的推理构建了机器学习应用程序。 新一代数据仓库实际上是数据湖,对那些用于构建和训练机器学习模型的清洗,整合和验证的数据进行管理。例如,去年秋天在Amazon re:Invent 大会上,亚马逊网络服务公布了AWS Lake Formation。这种新的托管服务的明确目的是简化和加速安全数据湖的设置。然而,AWS Lake Formation 拥有云数据仓库的所有特点,尽管AWS并没有这样称呼它,实际上已经提供了一个面向决策支持应用程序的经典数据仓库。 AWS Lake Formation的架构和功能类似于数据仓库。实际上,AWS以这种方式来描述它:“数据湖是一个集中的,策划的和安全的存储库,它以原始形式存储所有数据并为分析做好准备。通过数据湖,您可以分解数据孤岛并组合不同类型的分析,以获商业洞察力并指导更好的业务决策。“ 另一个例子是 Databricks 最近宣布的 Delta Lake开源项目。 Delta Lake的明确目的(现在可以在Apache 2.0许可下使用)类似于AWS Lake格式:通过对数据湖中维护的数据集的聚合,清洗,管理和治理,以支持机器学习。 Delta Lake 位于现有的内部部署或云数据存储平台之上,可以从Apache Spark访问,例如HDFS,Amazon S3或Microsoft Azure blob存储。 Delta Lake将数据存储在Parquet中,以提供Databricks所称的“事务存储层”.Parquet是一种开源的列式存储格式,无论数据处理框架的选择如何,都可用于Hadoop生态系统中的任何项目。它通过乐观并发可串行化,快照隔离,数据版本控制,回滚和模式实施来支持ACID事务。 Delta Lake和AWS Lake Formation之间的一个关键区别是 Delta Lake 处理该管道中的批量和流数据。另一个是Delta Lake支持所有数据的ACID事务,允许数百个应用程序同时进行多次写入和读取。此外,开发人员可以访问每个Delta Lake的早期版本,以进行审计,回滚或重现其MLFlow机器学习实验的结果。 在最广泛的层面上,Delta Lake似乎与使用最广泛的开源数据仓库项目 Apache Hive 竞争,尽管 Hive 完全依赖基于 HDFS 的存储,并且直到最近才解决对ACID交易的支持。Hive 3一年前被宣布终于为基于Hadoop的数据仓库提供ACID支持。 Hive 3使用delta文件为事务CRUD(创建读取更新删除)表提供操作的原子性和快照隔离。 ...

July 9, 2019 · 1 min · jiezi

数据人看Feed流架构实践

背景Feed流:可以理解为信息流,解决的是信息生产者与信息消费者之间的信息传递问题。我们常见的Feed流场景有:1 手淘,微淘提供给消费者的首页商品信息,用户关注店铺的新消息等2 微信朋友圈,及时获取朋友分享的信息3 微博,粉丝获取关注明星、大V的信息4 头条,用户获取系统推荐的新闻、评论、八卦 关于Feed流的架构设计,包括以上场景中的很多业内专家给出了相应的思考、设计和实践。本人是大数据方向出身的技术人,所在的团队参与了阿里手淘、微淘Feed流的存储层相关服务,我们的HBase/Lindorm数据存储产品在公有云上也支持着Soul、趣头条、惠头条等一些受欢迎的新媒体、社交类产品。我们在数据存储产品的功能、性能、可用性上的一些理解,希望对真实落地一个Feed流架构可以有一些帮助,以及一起探讨Feed流的未来以及数据产品如何帮助Feed流进一步迭代。 本文希望可以提供两点价值: 1 Feed流当前的主流架构以及落地方案2 一个初创公司如何选择Feed流的架构演进路径 业务分析Feed流参与者的价值信息生产者希望信息支持格式丰富(文字、图片、视频),发布流畅(生产信息的可用性),订阅者及时收到消息(时效性),订阅者不漏消息(传递的可靠性) 信息消费者希望及时收到关注的消息(时效性),希望不错过朋友、偶像的消息(传递的可靠性),希望获得有价值的消息(解决信息过载) 平台希望吸引更多的生产者和消费者(PV、UV),用户更长的停留时间,广告、商品更高的转化率 Feed信息传递方式一种是基于关系的消息传递,关系通过加好友、关注、订阅等方式建立,可能是双向的也可能是单向的。一种是基于推荐算法的,系统根据用户画像、消息画像利用标签分类或者协同过滤等算法向用户推送消息。微信和微博偏向于基于关系,头条、抖音偏向于基于推荐。 Feed流的技术难点互联网场景总是需要一定规模才能体现出技术的瓶颈,下面我们先看两组公开数据: 新浪微博为例,作为移动社交时代的重量级社交分享平台,2017年初日活跃用户1.6亿,月活跃用户近3.3亿,每天新增数亿条数据,总数据量达千亿级,核心单个业务的后端数据访问QPS高达百万级(来自 Feed系统架构与Feed缓存模型) 截止2016年12月底,头条日活跃用户7800W,月活跃用户1.75亿,单用户平均使用时长76分钟,用户行为峰值150w+msg/s,每天训练数据300T+(压缩后),机器规模万级别(来自 今日头条推荐系统架构设计实践) 上面还是两大巨头的历史指标,假设一条消息1KB那么千亿消息约93TB的数据量,日增量在几百GB规模且QPS高达百万,因此需要一个具备高读写吞吐,扩展性良好的分布式存储系统。用户浏览新消息期望百毫秒响应,希望新消息在秒级或者至少1分钟左右可见,对系统的实时性要求很高,这里需要多级的缓存架构。系统必须具备高可用,良好的容错性。最后这个系统最好不要太贵。 因此我们需要一个高吞吐、易扩展、低延迟、高可用、低成本的Feed流架构 主流架构图1是对Feed流的最简单抽象,完成一个从生产者向消费者传递消息的过程。 消息和关系首先,用户在APP侧获得的是一个Feed ID列表,这个列表不一定包含了所有的新消息,用户也不一定每一个都打开浏览,如果传递整个消息非常浪费资源,因此产生出来的消息首先生成主体和索引两个部分,其中索引包含了消息ID和元数据。其次一个应用总是存在关系,基于关系的传递是必不可少的,也因此一定有一个关系的存储和查询服务。 消息本身应该算是一种半结构化数据(包含文字,图片,短视频,音频,元数据等)。其读写吞吐量要求高,读写比例需要看具体场景。总的存储空间大,需要很好的扩展性来支撑业务增长。消息可能会有多次更新,比如内容修改,浏览数,点赞数,转发数(成熟的系统会独立一个counter模块来服务这些元数据)以及标记删除。消息一般不会永久保存,可能要在1年或者3年后删除。 综上,个人推荐使用HBase存储 HBase支持结构化和半结构化数据;具有非常好的写入性能,特别对于Feed流场景可以利用批量写接口单机(32核64GB)达到几十万的写入效率;HBase具备非常平滑的水平扩展能力,自动进行Sharding和Balance;HBase内置的BlockCache加上SSD盘可以提供ms级的高并发读;HBase的TTL特性可以自动的淘汰过期数据;利用数据复制搭建一个冷热分离系统,新消息存储在拥有SSD磁盘和大规格缓存的热库,旧数据存储在冷库。运用编码压缩有效的控制存储成本,见HBase优化之路-合理的使用编码压缩 对于关系服务,其写入操作是建立关系和删除关系,读取操作是获取关系列表,逻辑上仅需要一个KV系统。如果数据量较少可以使用RDS,如果数据量较大推荐使用HBase。如果对关系的QPS压力大可以考虑用Redis做缓存。 消息传递讲到Feed流一定会有关于推模式和拉模式的讨论,推模式是把消息复制N次发送到N个用户的收信箱,用户想看消息时从自己的收信箱直接获取。拉模式相反,生产者的消息写入自己的发信箱,用户想看消息时从关注的M个发信箱中收集消息。 推模式实现相对简单,时效性也比较好。拉模式要想获得好的性能需要多级的缓存架构。推模式重写,拉模式重读,Feed流场景下写的聚合效果要优于读,写可以大批量聚合。N越大,写入造成的数据冗余就越大。M越大,读消耗的资源越大。 随着业务的增长,推模式资源浪费会越发严重。原因在于两点:第一存在着大量的僵尸账号,以及大比例的非活跃用户几天或者半个月才登陆一次;第二信息过载,信息太多,重复信息太多,垃圾信息太多,用户感觉有用的信息少,消息的阅读比例低。这种情况下推模式相当一部分在做无用功,白白浪费系统资源。 是推?是拉?还是混合?没有最好的架构,只有适合的场景~ 基于关系的传递图6是纯推模式的架构,该架构有3个关键的部分 异步化。生产者提交消息首先写入一个队列,成功则表示发布成功,Dispatcher模块会异步的处理消息。这一点非常关键,首先生产者的消息发布体验非常好,不需要等待消息同步到粉丝的收信箱,发布延迟低成功率高;其次Dispatcher可以控制队列的处理速度,可以有效的控制大V账号造成的脉冲压力。多级队列。Dispatcher可以根据消费者的状态,信息的分类等划分不同的处理方式,分配不同的资源。比如对于大V账号的消息,当前活跃用户选择直接发送,保障消息的时效性,非活跃用户放入队列延迟发送。比如转发多的消息可以优先处理等。队列里的消息可以采用批量聚合写的方式提高吞吐。收信箱。假如有两亿用户,每个用户保留最新2000条推送消息。即便存储的是索引也是千亿的规模。收信箱一般的表结构为用户ID+消息序列 + 消息ID + 消息元数据,消息序列是一个递增的ID,需要存储一个偏移量表示上次读到的消息序列ID。用户读取最新消息 select * from inbox where 消息序列 > offset。 推荐使用HBase实现收信箱 HBase单机批量写能力在几十万并且可以水平扩展。HBase的高效前缀扫描非常适合读取最新的消息。HBase的TTL功能可以对数据定义生命周期,高效的淘汰过期数据。HBase的Filter过滤器和二级索引可以有效的实现Inbox的搜索能力。消费者收信箱hbase表设计如下,其中序列号要保证递增,一般用时间戳即可,特别高频情况下可以用一个RDS来制造序列号 Rowkey消息元数据列状态列其它列MD5(用户ID)+用户ID+序列号消息ID、作者、发布时间、关键字等已读、未读 图7是推拉结合的模式 增加发信箱,大V的发布进入其独立的发信箱。非大V的发布直接发送到用户的收信箱。其好处是解决大量的僵尸账号和非活跃账号的问题。用户只有在请求新消息的时候(比如登陆、下拉消息框)才会去消耗系统资源。发信箱的多级缓存架构。一个大V可能有百万粉丝,一条热点消息的传播窗口也会非常短,即短时间内会对发信箱中的同一条消息大量重复读取,对系统挑战很大。终态下我们可能会选择两级缓存,收信箱数据还是要持久化的,否则升级或者宕机时数据就丢失了,所以第一层是一个分布式数据存储,这个存储推荐使用HBase,原因和Inbox类似。第二层使用redis缓存加速,但是大V过大可能造成热点问题还需要第三层本地缓存。缓存层的优化主要包括两个方向:第一提高缓存命中率,常用的方式是对数据进行编码压缩,第二保障缓存的可用性,这里涉及到对缓存的冗余。 基于推荐的传递图8是基于推荐的模型,可以看出它是在推拉结合的模式上融合了推荐系统。 引入画像系统,保存用户画像、消息画像(简单情况下消息画像可以放在消息元数据中)。画像用于推荐系统算法的输入。引入了临时收信箱,在信息过载的场景中,非大V的消息也是总量很大,其中不免充斥着垃圾、冗余消息,所以直接进入用户收信箱不太合适。收信箱和发信箱都需要有良好的搜索能力,这是推荐系统高效运行的关键。Outbox有缓存层,索引可以做到缓存里面;Inbox一般情况下二级索引可以满足大部分需求,但如果用户希望有全文索引或者任意维度的检索能力,还需要引入搜索系统如Solr/ES 用户画像使用HBase存储 画像一般是稀疏表,画像总维度可能在200+甚至更多,但单个用户的维度可能在几十,并且维度可能随业务不断变化。那么HBase的Schema free和稀疏表的能力非常适合这个场景,易用且节省大量存储空间。对画像的访问一般是单行读,hbase本身单行Get的性能就非常好。阿里云HBase在这个方向上做了非常多的优化,包括CCSMAP、SharedBucketCache、MemstoreBloomFilter、Index Encoding等,可以达到平均RT=1-2ms,单库99.9% <100ms。阿里内部利用双集群Dual Service可以做到 99.9% < 30ms,这一能力我们也在努力推到公有云。hbase的读吞吐随机器数量水平扩展。临时收信箱使用云HBase HBase的读写高吞吐、低延迟能力,这里不再重复。HBase提供Filter和全局二级索引,满足不同量级的搜索需求。阿里云HBase融合HBase与Solr能力,提供低成本的全文索引、多维索引能力。初创公司的迭代路径在业务发展的初期,用户量和资源都没有那么多,团队的人力投入也是有限的,不可能一上来就搞一个特别复杂的架构,“够用”就行了,重要的是 可以快速的交付系统要稳定未来可以从容的迭代,避免推倒重来本人水平有限,根据自身的经验向大家推荐一种迭代路径以供参考,如有不同意见欢迎交流 ...

July 3, 2019 · 1 min · jiezi

Linus-本尊来了为什么-KubeCon-越来越火

阿里妹导读: 从200人的小会议到3500 多位云原生和开源领域工程师齐聚一堂的大会,KubeCon 只用了四年,昨天,在KubeCon China 2019 上阿里巴巴宣布开源 OpenKruise,今天,Linus 本尊竟然现身会场!现在,我们继续连线会场,探索阿里云为开发者带来的多份重磅献礼。 2015年11月,第一届 KubeCon 在美国旧金山开始的时候,还只是个200人的小会议,2019年的7月,KubeCon 第二次在中国举办,就有 3500 多位云原生和开源领域工程师齐聚一堂。 连 Linux 及 Git 创始人 Linus Torvalds 本人都来到 KubeCon China 上海现场。Linux 基金会执行董事 Jim Zemlin 说道:“我见证了开源圈子的两大事件:一个是 Linux 的成功,一个就是 Kubernetes 和云原生的大爆发。开源是历史上最成功的全球创新推动者之一,Linux 已经成长为世界上最重要的软件平台,而云原生正以势如破竹之态爆发。” 中国在整个云原生运动中贡献巨大,中国的 K8s contributors 已经在全球所有贡献者中排名第二,超过 10% 的 CNCF 会员来自中国,26%的 Kubernetes 的认证供应商来自中国。 阿里云作为最早成为 CNCF member 的中国公司之一,一直在云原生技术领域不停地实践和探索。在阿里云已经是铂金会员的基础上,蚂蚁金服也最新加入 CNCF 成为黄金会员。 本次 KubeCon China,阿里云又发布了什么黑科技呢?一起来感受下。 拥抱社区,服务最广泛开发者:云原生应用管理与交付体系发布 整个云原生应用管理与交付体系包含五大项目,本次 KubeCon 两大项目率先亮相:国内首个开放云原生应用中心—— Cloud Native App Hub 和云原生应用自动化引擎—— OpenKruise。 ...

June 27, 2019 · 2 min · jiezi

云上的Growth-hacking之路打造产品的增长引擎

增长关乎产品的存亡增长!增长!增长!业务增长是每一个创业者每天面临的最大问题。无论你的产品是APP,还是web,或者是小程序,只能不断的维持用户的增长,才能向资本市场讲出一个好故事,融资活下去。活到最后的产品,才有机会盈利。 为了获取用户的增长,可以投放广告,也可以内容营销、社交传播、销售地推,或者持续的专注于产品优化。无论哪一种方式,我们都面临这几个问题: 运营活动,覆盖了多少用户?多少用户,开始使用产品?多少用户付费?多少用户持续的活跃?下一步,我们应该把精力放在哪些方面?是持续运营?还是开发新功能? 如果不能回答这些问题,无疑我们的运营活动或者开发就是盲人摸象,完全靠运气。为了解答这些问题,我们不妨关注一下growth hacking这种数据驱动的手段。 Growth Hacker的核心思想传统的市场营销策略,例如投放电视广告,覆盖了多少人,有多少人看过广告后进行了购买,多少人进行了复购,没有准确的数据进行衡量,只能依赖于资深专家根据经验判断。在互联网行业,每一个产品都是新的,前所未有的。每一个产品能不能存活,每一次运营的效果如何,没有多少经验可供借鉴,结果是不确定的。 GrowthHacking是兴起于硅谷的创业公司的marketing手段,旨在使用少量预算获得巨量增长。由于其极高的性价比和有效性,非常适合于创业公司,因而得到了广泛传播。 Growth Hacker的核心思想是通过数据指标,驱动运营决策,以及优化产品。Growthacker通过关注用户获取、用户转化、用户留存、用户推荐、盈利等核心的一系列指标,以及通过各种维度拆解,分析出下一步的增长决策。通过Growth Hacking,打造一个产品增长策略的闭环。 那么我们如何才能搭建出GrowthHacking架构,为自己的产品赋能呢? GrowthHacking之架构Growth Hacking 包含了数据的采集、存储、分析、报表、A/B test等系统,首先我们来看,传统的解决方案,搭建出GrowthHacking有哪些痛点: 搭建运营体系的痛点搭建运营体系的过程中,常常面临以下问题: 缺少数据,数据散落在各个地方,有的是app数据,有的是web数据,有的是小程序数据,没有一个统一的架构来把数据采集到一个地方。缺少一个分析平台。传统的策略,需要运维团队帮助搭建hadoop集群,需要专门团队持久运维。离线跑报表,一晚上才能拿到一次结果,周期太长。手工跑一次,几个小时过去了,有什么新的想法,不能及时验证。严重影响运营效率。借助云服务搭建的GrowthHacking技术架构为了解决以上问题, 日志服务提供了日志采集、存储、交互分析、可视化的一整套基础设施,可以帮助用户快速搭建出来灵活易用的Growthing Hacking的技术架构,每天的工作只需要专注于运营分析即可。 Growth Hacking首先从数据采集开始,定义清楚要采集的日志内容、格式。把各个终端、服务器的日志集中采集到云端的日志服务。后续通过日志服务提供的SQL实时分析功能,交互式的分析。定义一些常规报表,每日打开报表自动计算最新结果,也可以定义报告,自动发送最新报表。全部功能参考用户手册 此外,除了日志数据的分析,还可以为用户定义一些标签,存储在rds中,通过rds和日志的联合分析,挖掘不同标签对应的指标。 日志服务有如下特点: 免运维:一次完成数据的埋点、数据接入,之后只需专注于运营分析即可,无需专门的运维团队。实时性:用SQL实时计算,秒级响应。快人一步得到分析结果。灵活性:任意调整SQL,实时获取结果,非常适合交互式分析。弹性:遇到运营活动,流量突然暴涨,动动手指快速扩容。性价比:市场上常见的分析类产品,多采用打包价格,限制使用量。日志服务按量付费,价格更低,功能更强大。借助于日志服务提供的这套数据采集、存储、分析的基础设施。运营者可以从繁重的数据准备工作重解脱出来,专注于使用SQL去分析数据,配置报表,验证运营想法。 开始搭建GrowthHacking系统具体而言,Growth Hacking的架构可以拆分如下: 数据收集 定义埋点的规范,定义要采集的事件内容、字段、格式。通过Android SDK,iOS SDK, Web tracking等手段在客户端埋点。存储 选择日志服务的region。定义每一种日志存储的Project & LogStore。分析 开启分析之路,定义常规报表,或者交互式分析。通过分析结果,调整运营策略,有针对性的优化产品。基于日志服务,可以完成Growth Hacking的分析策略: 定义北极星指标。拉新分析。留存分析。事件分析。漏斗分析。用户分群。A/B test。在日志服务中,可以通过定义一系列仪表盘,来沉淀数据分析的结果。接下来的几篇文章中,将依次介绍如何在日志服务实现上述几种策略。 总结本文主要介绍Growth Hacking的整体架构,之后将用一系列文章介绍step by step如何介入数据,如何分析数据。 本文作者:云雷 阅读原文 本文为云栖社区原创内容,未经允许不得转载。

June 25, 2019 · 1 min · jiezi

Spark内置图像数据源初探

概述在Apache Spark 2.4中引入了一个新的内置数据源, 图像数据源.用户可以通过DataFrame API加载指定目录的中图像文件,生成一个DataFrame对象.通过该DataFrame对象,用户可以对图像数据进行简单的处理,然后使用MLlib进行特定的训练和分类计算.    本文将介绍图像数据源的实现细节和使用方法. 简单使用先通过一个例子来简单的了解下图像数据源使用方法. 本例设定有一组图像文件存放在阿里云的OSS上, 需要对这组图像加水印,并压缩存储到parquet文件中. 废话不说,先上代码: // 为了突出重点,代码简化图像格式相关的处理逻辑 def main(args: Array[String]): Unit = { val conf = new SparkConf().setMaster("local[*]") val spark = SparkSession.builder() .config(conf) .getOrCreate() val imageDF = spark.read.format("image").load("oss://<bucket>/path/to/src/dir") imageDF.select("image.origin", "image.width", "image.height", "image.nChannels", "image.mode", "image.data") .map(row => { val origin = row.getAs[String]("origin") val width = row.getAs[Int]("width") val height = row.getAs[Int]("height") val mode = row.getAs[Int]("mode") val nChannels = row.getAs[Int]("nChannels") val data = row.getAs[Array[Byte]]("data") Row(Row(origin, height, width, nChannels, mode, markWithText(width, height, BufferedImage.TYPE_3BYTE_BGR, data, "EMR"))) }).write.format("parquet").save("oss://<bucket>/path/to/dst/dir") } def markWithText(width: Int, height: Int, imageType: Int, data: Array[Byte], text: String): Array[Byte] = { val image = new BufferedImage(width, height, imageType) val raster = image.getData.asInstanceOf[WritableRaster] val pixels = data.map(_.toInt) raster.setPixels(0, 0, width, height, pixels) image.setData(raster) val buffImg = new BufferedImage(width, height, imageType) val g = buffImg.createGraphics g.drawImage(image, 0, 0, null) g.setColor(Color.red) g.setFont(new Font("宋体", Font.BOLD, 30)) g.drawString(text, width/2, height/2) g.dispose() val buffer = new ByteArrayOutputStream ImageIO.write(buffImg, "JPG", buffer) buffer.toByteArray }从生成的parquet文件中抽取一条图像二进制数据,保存为本地jpg,效果如下: ...

June 17, 2019 · 3 min · jiezi

TableStore-海量结构化数据分层存储方案

前言表格存储是阿里云自研分布式存储系统,可以用来存储海量结构化、半结构化的数据。表格存储支持高性能和容量型两种实例类型。高性能使用SSD的存储介质,针对读多写多的场景都有较好的访问延时。容量型使用的是SSD和SATA混合的存储介质。对写多的场景,性能接近高性能,读方面,如果遇到冷数据产生读SATA盘的话,延时会比高性能上涨一个量级。在海量数据存储场景下,例如时序场景,我们会希望最新的数据可以支持高性能查询,较早的数据的读写频次都会低很多。这时候一个基于表格存储高性能和容量型存储分层的需求就产生了。 方案细节表格存储近期对外正式发布的全增量一体的通道服务(参考文档),通道服务基于表格存储数据接口之上的全增量一体化服务。通道服务为用户提供了增量、全量、增量加全量三种类型的分布式数据实时消费通道。有了通道服务,我们可以很方便的构建从高性能实例下的表到容量型表之间的实时数据同步,进而可以在高性能表上使用表格存储的特性数据生命周期(参考文档),根据业务需求设置一个合理的TTL。总体来说就可以构建一个如下图所示的架构: 整个数据的流动过程如下: 业务写入端直接写入高性能实例高性能实例中的数据通过通道服务同步至容量型高性能实例中的老数据自动过期,减少存储量占用用户查询请求根据时序查询条件,判断是否是近期数据 近期数据查询进入高性能,毫秒级别返回较早数据查询进入容量型,几十毫秒后返回代码和操作流程:在高性能实例上根据业务主键需求创建数据表,并设置合理的数据TTL,然后在容量型下创建相同的schema的表用来持久化存储所有数据。 然后在通道页面创建一个全增量类型的通道: 通过控制台可以简单清晰的查看到同步的状态,并发,进度等信息: 下面贴一下通过Tunnel进行复制同样schema表TableStore表的Sample代码: func main () { //高性能实例的信息 tunnelClient := tunnel.NewTunnelClient("", "", "", "") //容量型实例的信息 client := tablestore.NewClient("", "", "", "") //配置callback到SimpleProcessFactory,配置消费端TunnelWorkerConfig workConfig := &tunnel.TunnelWorkerConfig{ ProcessorFactory: &tunnel.SimpleProcessFactory{ ProcessFunc: replicateDataFunc, CustomValue: client, }, } //使用TunnelDaemon持续消费指定tunnel daemon := tunnel.NewTunnelDaemon(tunnelClient, "", workConfig) err := daemon.Run() if err != nil { fmt.Println("failed to start tunnel daemon with error:", err) }}func replicateDataFunc(ctx *tunnel.ChannelContext, records []*tunnel.Record) error { client := ctx.CustomValue.(*tablestore.TableStoreClient) fmt.Println(client) for _, rec := range records { fmt.Println("tunnel record detail:", rec.String()) updateRowRequest := new(tablestore.UpdateRowRequest) updateRowRequest.UpdateRowChange = new(tablestore.UpdateRowChange) updateRowRequest.UpdateRowChange.TableName = "coldtable" updateRowRequest.UpdateRowChange.PrimaryKey = new(tablestore.PrimaryKey) updateRowRequest.UpdateRowChange.SetCondition(tablestore.RowExistenceExpectation_IGNORE) for _, pk := range rec.PrimaryKey.PrimaryKeys { updateRowRequest.UpdateRowChange.PrimaryKey.AddPrimaryKeyColumn(pk.ColumnName, pk.Value) } for _, col := range rec.Columns { if col.Type == tunnel.RCT_Put { updateRowRequest.UpdateRowChange.PutColumn(*col.Name, col.Value) } else if col.Type == tunnel.RCT_DeleteOneVersion { updateRowRequest.UpdateRowChange.DeleteColumnWithTimestamp(*col.Name, *col.Timestamp) } else { updateRowRequest.UpdateRowChange.DeleteColumn(*col.Name) } } _, err := client.UpdateRow(updateRowRequest) if err != nil { fmt.Println("hit error when put record to cold data", err) } } fmt.Println("a round of records consumption finished") return nil}总结通过通道服务,存储在表格存储中的结构化,半结构化数据可以实时流出,进行加工,萃取,计算或进行同步。如果是想进一步降低冷数据的存储成本,可以参考这篇文章把表格存储的数据备份到OSS归档存储。 ...

June 5, 2019 · 1 min · jiezi

DTCC-2019-阿里云TSDB-教你解锁时序时空数据库的种种黑科技

摘要:阿里云TSDB是阿里自研的一种高性能,低成本,稳定可靠的在线时序时空数据库产品。该产品统一了阿里巴巴集团90%以上的APM数据和事件型数据的存储和计算,并在广泛应用于外部的物联网,工业制造,电力,化工以及IT运维等行业。本文中,阿里云智能数据库产品事业部技术专家伊翼就为大家介绍了阿里云TSDB的种种黑科技。专家简介:伊翼(花名:老滚)。阿里云智能数据库产品事业部技术专家,主要从事TSDB核心引擎的研发工作。 直播回放 链接:https://yq.aliyun.com/live/1044 议题PPT下载,戳这里! https://yq.aliyun.com/download/3563 本次分享的内容主要包括以下四个方面: 走进时序数据库认识阿里云TSDB阿里云TSDB技术内幕未来与展望一、走进时序数据库熟悉而又陌生的时序数据时序数据库本身是一个比较新的概念,直到5年前,DB-Engine才将时序数据库列为一个独立的分类。虽然时序数据库的概念比较新,但是时序数据却由来已久。从古至今,在我们的日常生活中,时序数据从未缺席。古代记录灾害与祥瑞出现时间的县志也能够发挥类似今天时序数据库的作用,帮助决策者指定相关的决策,地方官员可以根据县志中的记录判断是否需要进行祭祀,也可以决策是否需要向中央朝廷报告祥瑞以谋取升迁等,因此当时的县志也发挥了类似于OLAP的功能。但由于理念和技术的限制,当时所记录的时序数据信息是有限的,精度也是有限的。 技术发展到今天,时序数据所能记录的信息和精度都有了极大的提升。如下图所示的是杭州市空气监测时序数据片段。由此可以看出,时序数据有一些共同的特征,比如多样的指标值、比较稳定的采集频率以及任何一个数据点都有时间戳。在技术飞速发展的今天,时序数据的规模越来越大,增长速度也越来越快。因此,我们需要面对一些问题,比如面对如此大规模的时序数据,应该将其存放在哪里。 时序数据库的概念 在十几年前,时序数据只能选择存放在关系型数据库中,但是随着通信技术的发展,特别是互联网技术的发展,时序数据的增长速度呈现指数级别,使用关系型数据库来存储时序数据显然跟不上时代的节奏了,所以时序数据库应运而生。时序数据库就是一类专门为处理时间序列数据而设计并优化的数据库管理系统。 相较传统的关系型数据库,时序数据库的特点如下: 存储的任何一条数据记录都必然带一个时间戳 通常高频访问热数据 数据写入频率相对稳定,且远大于数据读取的频率 通常按照时间窗口查询数据 基本不提供单点数据的更新或删除功能 无需提供类似关系型数据库事务级别的数据强一致性 目前,使用时序数据库的行业应用越来越广泛。 电力行业:智能电表、电网、发电设备的集中监测 交通行业:实时路况,路口流量监测,卡口数据的采集与分析 石油石化:油井、运输管线、运输车队的实时监测 物流行业:车辆、集装箱的追踪监测 环境监测:天气、空气、水文、地质环境等监测 物联网:电梯、锅炉、机械、水表、气表等各种联网设备的数据采集、分析与检测 军工行业:军事装备的数据采集、存储与分析 制造业:生产过程管控,流程数据、供应链数据采集与分析 互联网:互联网应用的PV/UV数据,基础设施的性能监控 时序数据库的迅猛发展 由于时序数据库的适用性非常广泛,因此其在DB-Engine上的受关注度一直处于增长态势。面对这样的关注度增长态势,时序数据库技术的发展也作出了积极的响应。无论是在开源领域还是商用领域,都推出了大量的时序数据库产品,比如InfluxDB、OpenTSDB、TimescaleDB以及阿里云时序时空TSDB等。 二、认识阿里云TSDB阿里云时序时空TSDB架构 如下图所示的是阿里云时序时空TSDB的整体架构,从左到右依次是采集端、TSDB服务端以及靠近最终用户和开发者的实例端。在采集端,阿里云时序时空TSDB采用了边缘计算的解决方案,其可以应用在资源受限或者网络状况不稳定的场景下。采集端可以和服务端进行打通,服务端可以向边缘下发各种各样的规则,使得边缘端能够直接进行数据清洗和计算,这就实现了“边云一体化”。图中的中间部分是TSDB的服务端,它也分为几个组件,TS计算引擎主要负责预聚合、降精度以及持续查询,TSQL引擎主要负责处理SQL查询,此外还有一个基于已经训练好的模型算法库,提供各行业定制化解决方案的智能引擎。在这三个引擎下面就是TSDB的时序引擎。 接下来为大家介绍阿里云时序时空TSDB在功能层面的一些特性。 特性1:强力的数据模型支持 阿里云TSDB支持多样的数据模型,同时支持了多值模型和单值模型。举例而言,温度监控设备需要每间隔一段时间向数据库上报温度数据,其上报的数据中必然带有一个时间戳以及温度值,这样最基础的数据形式称之为单值模型。而如果上报的数据中不仅仅包含了一个时间戳和室内温度,还包含了室外温度以及空气湿度等,这样的数据就可以称之为多值模型。其实,时序数据库对于多值模型的支持并不是行业要求,因此即便是在开源领域,各种数据库对于多值模型的支持也不同。支持多值模型的好处在于可以提升数据的写入效率,另外一方面就是对于业务应用的开发者而言可以使得设计更加直观。 除了对于多值模型的支持之外,阿里云TSDB还支持多种的数据类型,不仅支持传统数据类型,还能够支持字符串类型数据,并且能够支持精确到毫秒的时间戳。 特性2:降采样&数据聚合 对于时序数据库而言,降采样和数据聚合也是非常重要的特性。依旧以温度采集为例,温度采集设备可能上报数据的频率非常高,比如每秒钟上传一次数据,但是在做数据查询的时候并不需要按照原始的数据采集频率进行分析和展示,因此就需要对于上报的数据进行降采样操作,比如将按秒采样的数据降采样为按小时或者按天进行分析和展示。 与之相对的,数据聚合在分析和展示中也非常重要。通常情况下,有很多个数据采集设备,不同设备每隔一段时间上报数据的时候就认为这些数据属于不同的时间序列,而随着设备的增多,必然使得时间序列变得非常多,而在做分析和查询的时候并不需要对多个时间序列进行分析,只需要将其进行汇总,比如使用汇总后的平均值进行分析。这种情况下就是对于一个数据的指标值按照时间维度将多个时间序列聚合成一条,这就是数据聚合。无论是降采样还是数据聚合,阿里云TSDB都提供了非常丰富的聚合算子,有了这样的能力,就可以仅凭借阿里云原生能力来满足各种复杂的查询分析场景。 特性3:SQL查询能力 由于时序数据库本身属于比较新的概念,为了降低开发人员以及数据分析人员使用时序数据库的门槛和学习成本,阿里云TSDB也提供了基于SQL的查询接口。有了SQL的查询接口,用户就可以非常方便地使用SQL来操作时序模型。而阿里云TSDB的SQL接口也基于时序场景进行了算法上的优化,可以将SQL中的过滤、聚合等操作全部下推到TSDB的内核中,这样就可以最优化的方式来处理时序数据的分析和查询。 特性4:内置对接Prometheus 在最新版的阿里云TSDB中,已经实现了内置对接Prometheus的能力。Prometheus是一个非常适用于监控Kubernetes集群的工具,但是其对于监控数据的存储能力比较薄弱,虽然社区也考虑到这一点并且提供了Prometheus Adapter的第三方组件来将Prometheus的数据对接到各种各样的数据源上,但是当数据链路中增加一个组件就意味着查询性能的降低。为了在阿里云TSDB对接Prometheus的同时保持较高的查询效率,TSDB内置了对接Prometheus的能力。经过测试,内置对接Prometheus的方式相对于经由Prometheus Adapter中转方式的查询性能要高很多。 特性5:边缘计算能力 阿里云TSDB的边缘端计算能力处于行业内的领先地位。因为在物联网应用和工业大数据的应用场景中,无法保证数据的采集端是实时在线的,这样的场景就是边缘计算的用武之地。考虑到用户数据的可用性,TSDB边缘端再设计的时候也采用了高可用架构。当网络状况恢复稳定的时候,边缘段会将数据同步给阿里云TSDB服务端,这样可以方便用户在服务端进行统一的数据分析和查询。 与其他时序数据库的功能对比 下图中的表格列出了目前主流的时序数据库在功能特性上的支持情况对比。 接下来为大家介绍几个阿里云TSDB实际的应用案例。 案例1: 某互联网餐饮系统研发企业 该企业在自己的解决方案中将阿里云TSDB整合了进去,利用阿里云TSDB高性能写入将整个链路中的所有时序数据以及业务指标全部写入了TSDB中,借助TSDB优越的查询性能以及将监控系统整合在一起,从而支持了对于整个解决方案中所有链路节点的实时监控,与此同时提高了系统的整体稳定性。 案例2:某直播平台运维监控APM 该直播平台原来的APM系统中将所有采集到的时序数据全部通过消息队列存储到OpenTSDB集群中,但是很快就发现OpenTSDB的写入存在瓶颈,而且OpenTSDB在时序索引方面天生存在薄弱点,因此在面向较为复杂的查询的时候,几乎处于不可用的状态。在经过比较之后,该直播平台选择使用阿里云TSDB来替换所有的OpenTSDB,并且加大了写入规模,从实际效果来看,阿里云TSDB达到了所期望的效果。 案例3: 阿里巴巴集团内部全业务对接 最后的一个案例是阿里巴巴集团内部的案例。从上图可以看出,无论是底层的资源调控、整体监控还是上层应用,阿里云TSDB已经覆盖了阿里集团内部的130余个线上业务。而在2018年双11大促期间,阿里云TSDB承接的来自于阿里集团内部的各个业务的时序数据,写入TPS峰值达到了4000万TPS,查询峰值达到了2万QPS,累计时间线数量超过了100亿。 三、阿里云TSDB技术内幕时序时空TSDB引擎的核心技术 阿里云时序时空TSDB引擎具有很多的核心技术,在本次分享中主要为大家介绍数据压缩、时序索引以及聚合引擎三个方面的核心技术。 数据压缩 时序数据的规模增长速度很快,而用户往往出于日后需要进行查询或者分析的考虑,希望所能够存储的时序数据越多越好。但是通常情况下,对于大规模时序数据的查询而言,往往非常困难。一方面需要满足用户对于查询的需求,另外一方面需要有效地降低用户存储的成本。针对于以上两方面的诉求,阿里云TSDB研发了一套数据压缩技术。下图中左侧是一张示意图,其每一行代表一个时间序列,其列代表数据点。在没有进行数据压缩的情况下,如果想要将其数据调整到毫秒级别,就会发现其列数会增加到360万,这样的数据量是非常可观的,所以必须要进行压缩。阿里云TSDB所采用的压缩思路借鉴了Facebook Gorilla的实现思路,会将时间戳和数据两块压缩成两个大数据块,对时间戳采用了delta-delta的压缩方法,而对于不同的数据类型则采用了相应的数据压缩算法。在压缩成两个大数据块基础之上,再对其进行通用的块压缩。经过两部分的压缩就使得数据压缩比达到15:1的效果。 如下图所示的是真实场景下的数据压缩效果。原始情况下数据大约6TB,一开始尝试最普通的块压缩,将数据压缩到了715G,但此时的数据压缩比不到10:1,而采用先进行时序压缩再追加一次块压缩后使得最终数据压缩为413G,压缩比达到了15:1。那么,追求如此之高的数据压缩比有什么好处呢?其实主要有两个好处,第一个好处就是能够帮助用户降低存储成本;另外一个好处就是因为数据压缩比很大,因此当在进行大范围的时序数据查询的时候,IO效率会非常高,在这个例子中可以将查询延时降低约50%。 时序索引 TSDB的整体查询流程非常简单,当用户指定了一个查询条件,阿里云TSDB首先会解析这个查询条件,同时做一定程度的优化。接下来会做两件事情,一件是将查询条件扔给时序索引模块,时序索引模块会根据查询条件计算命中的时间线数量以及相关信息,拿到时间线信息之后再将时间线集合扔给聚合索引,聚合索引再到底层存储上面获取相应的时间数据并进行降采样、聚合等操作。虽然这一过程看上去比较简单,但是却存在很多值得研究的点。 如下图所示的是时间线的生命周期,如果用户想要查询T2-T3时间范围内的数据,肯定不希望数据中包含T0-T2已经消亡或者说不再有新的数据进来的时间线,所以这部分也是时序索引可以进一步研究的地方。 ...

June 4, 2019 · 1 min · jiezi

基于大数据的舆情分析系统架构-架构篇

前言互联网的飞速发展促进了很多新媒体的发展,不论是知名的大V,明星还是围观群众都可以通过手机在微博,朋友圈或者点评网站上发表状态,分享自己的所见所想,使得“人人都有了麦克风”。不论是热点新闻还是娱乐八卦,传播速度远超我们的想象。可以在短短数分钟内,有数万计转发,数百万的阅读。如此海量的信息可以得到爆炸式的传播,如何能够实时的把握民情并作出对应的处理对很多企业来说都是至关重要的。大数据时代,除了媒体信息以外,商品在各类电商平台的订单量,用户的购买评论也都对后续的消费者产生很大的影响。商家的产品设计者需要汇总统计和分析各类平台的数据做为依据,决定后续的产品发展,公司的公关和市场部门也需要根据舆情作出相应的及时处理,而这一切也意味着传统的舆情系统升级成为大数据舆情采集和分析系统。分析完舆情场景后,我们再来具体细化看下大数据舆情系统,对我们的数据存储和计算系统提出哪些需求: 海量原始数据的实时入库:为了实现一整套舆情系统,需要有上游原始输出的采集,也就是爬虫系统。爬虫需要采集各类门户,自媒体的网页内容。在抓取前需要去重,抓取后还需要分析提取,例如进行子网页的抓取。原始网页数据的处理:不论是主流门户还是自媒体的网页信息,抓取后我们需要做一定的数据提取,把原始的网页内容转化为结构化数据,例如文章的标题,摘要等,如果是商品点评类消息也需要提取有效的点评。结构化数据的舆情分析:当各类原始输出变成结构化的数据后,我们需要有一个实时的计算产品把各类输出做合理的分类,进一步对分类后的内容进行情感打标。根据业务的需求这里可能会产生不同的输出,例如品牌当下是否有热点话题,舆情影响力分析,转播路径分析,参与用户统计和画像,舆论情感分析或者是否有重大预警。舆情分析系统中间和结果数据的存储,交互分析查询:从网页原始数据清洗到最终的舆情报表这中间会产生很多类型的数据。这些数据有的会提供给数据分析同学进行舆情分析系统的调优,有的数据会提供给业务部门根据舆情结果进行决策。这些查询可能会很灵活,需要我们的存储系统具备全文检索,多字段组合灵活的交互分析能力。重大舆情事件的实时预警:对于舆情的结果除了正常的搜索和展示需求以外,当有重大事件出现我们需要能做到实时的预警。我们计划分两篇介绍完整的舆情新架构,第一篇主要是提供架构设计,会先介绍时下主流的大数据计算架构,并分析一些优缺点,然后引入舆情大数据架构。第二篇会有完整的数据库表设计和部分示例代码。大家敬请期待。 系统设计需求分析 结合文章开头对舆情系统的描述,海量大数据舆情分析系统流程图大体如下: 原始网页存储库,这个库需要能支持海量数据,低成本,低延时写入。网页数据写入后,要做实时结构化提取,提取出来的数据再进行降噪,分词,图片ocr处理等。对分词文本,图片进行情感识别产生舆情数据结果集。传统的离线全量计算很难满足舆情系统的时效性需求。计算引擎在做数据处理时,可能还需要从存储库中获取一些元数据,例如用户信息,情感词元数据信息等。除了实时的计算链路,对存量数据定期要做一些聚类,优化我们的情感词识别库,或者上游根据业务需要触发情感处理规则更新,根据新的情感打标库对存量数据做一次舆情计算。舆情的结果数据集有不同类的使用需求。对于重大舆情,需要做实时的预警。完整的舆情结果数据展示层需要支持全文检索,灵活的属性字段组合查询。业务上可能根据属性字段中的置信度,舆情时间,或者关键词组合进行分析。根据前面的介绍,舆情大数据分析系统需要两类计算,一类是实时计算包括海量网页内容实时抽取,情感词分析并进行网页舆情结果存储。另一类是离线计算,系统需要对历史数据进行回溯,结合人工标注等方式优化情感词库,对一些实时计算的结果进行矫正等。所以在系统设计上,需要选择一套既可以做实时计算又能做批量离线计算的系统。在开源大数据解决方案中,Lambda架构恰好可以满足这些需求,下面我们来介绍下Lambda的架构。 Lambda架构 (wiki) Lambda架构可以说是Hadoop,Spark体系下最火的大数据架构。这套架构的最大优势就是在支持海量数据批量计算处理(也就是离线处理)同时也支持流式的实时处理(即热数据处理)。具体是如何实现的呢,首先上游一般是一个队列服务例如kafka,实时存储数据的写入。kafka队列会有两个订阅者,一个是全量数据即图片中上半部分,全量数据会被存储在类似HDFS这样的存储介质上。当有离线计算任务到来,计算资源(例如Hadoop)会访问存储系统上的全量数据,进行全量批计算的处理逻辑。经过map/reduce环节后全量的结果会被写入一个结构化的存储引擎例如Hbase中,提供给业务方查询。队列的另一个消费订阅方是流计算引擎,流计算引擎往往会实时的消费队列中的数据进行计算处理,例如Spark Streaming实时订阅Kafka的数据,流计算结果也会写入一个结构化数据引擎。批量计算和流计算的结果写入的结构化存储引擎即上图标注3的"Serving Layer",这一层主要提供结果数据的展示和查询。在这套架构中,批量计算的特点是需要支持处理海量的数据,并根据业务的需求,关联一些其他业务指标进行计算。批量计算的好处是计算逻辑可以根据业务需求灵活调整,同时计算结果可以反复重算,同样的计算逻辑多次计算结果不会改变。批量计算的缺点是计算周期相对较长,很难满足实时出结果的需求,所以随着大数据计算的演进,提出了实时计算的需求。实时计算在Lambda架构中是通过实时数据流来实现,相比批处理,数据增量流的处理方式决定了数据往往是最近新产生的数据,也就是热数据。正因为热数据这一特点,流计算可以满足业务对计算的低延时需求,例如在舆情分析系统中,我们往往希望舆情信息可以在网页抓取下来后,分钟级别拿到计算结果,给业务方充足的时间进行舆情反馈。下面我们就来具体看一下,基于Lambda架构的思想如何实现一套完整的舆情大数据架构。 开源舆情大数据方案通过这个流程图,让我们了解了整个舆情系统的建设过程中,需要经过不同的存储和计算系统。对数据的组织和查询有不同的需求。在业界基于开源的大数据系统并结合Lambda架构,整套系统可以设计如下: 系统的最上游是分布式的爬虫引擎,根据抓取任务抓取订阅的网页原文内容。爬虫会把抓取到的网页内容实时写入Kafka队列,进入Kafka队列的数据根据前面描述的计算需求,会实时流入流计算引擎(例如Spark或者Flink),也会持久化存储在Hbase,进行全量数据的存储。全量网页的存储可以满足网页爬取去重,批量离线计算的需求。流计算会对原始网页进行结构化提取,将非结构化网页内容转化为结构数据并进行分词,例如提取出网页的标题,作者,摘要等,对正文和摘要内容进行分词。提取和分词结果会写回Hbase。结构化提取和分词后,流计算引擎会结合情感词库进行网页情感分析,判断是否有舆情产生。流计算引擎分析的舆情结果存储Mysql或者Hbase数据库中,为了方便结果集的搜索查看,需要把数据同步到一个搜索引擎例如Elasticsearch,方便进行属性字段的组合查询。如果是重大的舆情时间,需要写入Kafka队列触发舆情报警。全量的结构化数据会定期通过Spark系统进行离线计算,更新情感词库或者接受新的计算策略重新计算历史数据修正实时计算的结果。开源架构分析上面的舆情大数据架构,通过Kafka对接流计算,Hbase对接批计算来实现Lambda架构中的“batch view”和“real-time view”,整套架构还是比较清晰的,可以很好的满足在线和离线两类计算需求。但是把这一套系统应用在生产并不是一件容易的事情,主要有下面一些原因。 整套架构涉及到非常多的存储和计算系统包括:Kafka,Hbase,Spark,Flink,Elasticsearch。数据会在不同的存储和计算系统中流动,运维好整套架构中的每一个开源产品都是一个很大的挑战。任何一个产品或者是产品间的通道出现故障,对整个舆情分析结果的时效性都会产生影响。为了实现批计算和流计算,原始的网页需要分别存储在Kafka和Hbase中,离线计算是消费hbase中的数据,流计算消费Kafka的数据,这样会带来存储资源的冗余,同时也导致需要维护两套计算逻辑,计算代码开发和维护成本也会上升。舆情的计算结果存储在Mysql或者Hbase,为了丰富组合查询语句,需要把数据同步构建到Elasticsearch中。查询的时候可能需要组合Mysql和Elasticsearch的查询结果。这里没有跳过数据库,直接把结果数据写入Elasticsearch这类搜索系统,是因为搜索系统的数据实时写入能力和数据可靠性不如数据库,业界通常是把数据库和搜索系统整合,整合下的系统兼备了数据库和搜索系统的优势,但是两个引擎之间数据的同步和跨系统查询对运维和开发带来很多额外的成本。新的大数据架构Lambda plus通过前面的分析,相信大家都会有一个疑问,有没有简化的的大数据架构,在可以满足Lambda对计算需求的假设,又能减少存储计算以及模块的个数呢。Linkedin的Jay Kreps提出了Kappa架构,关于Lambda和Kappa的对比可以参考"云上大数据方案"这篇,这里不展开详细对比,简单说下,Kappa为了简化两份存储,取消了全量的数据存储库,通过在Kafka保留更长日志,当有回溯重新计算需求到来时,重新从队列的头部开始订阅数据,再一次用流的方式处理Kafka队列中保存的所有数据。这样设计的好处是解决了需要维护两份存储和两套计算逻辑的痛点,美中不足的地方是队列可以保留的历史数据毕竟有限,难以做到无时间限制的回溯。分析到这里,我们沿着Kappa针对Lambda的改进思路,向前多思考一些:假如有一个存储引擎,既满足数据库可以高效的写入和随机查询,又能像队列服务,满足先进先出,是不是就可以把Lambda和Kappa架构揉合在一起,打造一个Lambda plus架构呢?新架构在Lambda的基础上可以提升以下几点: 在支持流计算和批计算的同时,让计算逻辑可以复用,实现“一套代码两类需求”。统一历史数据全量和在线实时增量数据的存储,实现“一份存储两类计算”。为了方便舆情结果查询需求,“batch view”和“real-time view”存储在既可以支持高吞吐的实时写入,也可以支持多字段组合搜索和全文检索。总结起来就是整套新架构的核心是解决存储的问题,以及如何灵活的对接计算。我们希望整套方案是类似下面的架构: 数据流实时写入一个分布式的数据库,借助于数据库查询能力,全量数据可以轻松的对接批量计算系统进行离线处理。数据库通过数据库日志接口,支持增量读取,实现对接流计算引擎进行实时计算。批计算和流计算的结果写回分布式数据库,分布式数据库提供丰富的查询语意,实现计算结果的交互式查询。整套架构中,存储层面通过结合数据库主表数据和数据库日志来取代大数据架构中的队列服务,计算系统选取天然支持批和流的计算引擎例如Flink或者Spark。这样一来,我们既可以像Lambda进行无限制的历史数据回溯,又可以像Kappa架构一样一套逻辑,存储处理两类计算任务。这样的一套架构我们取名为“Lambda plus”,下面就详细展开如何在阿里云上打造这样的一套大数据架构。 云上舆情系统架构在阿里云众多存储和计算产品中,贴合上述大数据架构的需求,我们选用两款产品来实现整套舆情大数据系统。存储层面使用阿里云自研的分布式多模型数据库Tablestore,计算层选用Blink来实现流批一体计算。 这套架构在存储层面,全部基于Tablestore,一个数据库解决不同存储需求,根据之前舆情系统的介绍,网页爬虫数据在系统流动中会有四个阶段分别是原始网页内容,网页结构化数据,分析规则元数据和舆情结果,舆情结果索引。我们利用Tablestore宽行和schema free的特性,合并原始网页和网页结构化数据成一张网页数据。网页数据表和计算系统通过Tablestore新功能通道服务进行对接。通道服务基于数据库日志,数据的组织结构按照数据的写入顺序进行存储,正是这一特性,赋能数据库具备了队列流式消费能力。使得存储引擎既可以具备数据库的随机访问,也可以具备队列的按照写入顺序访问,这也就满足我们上面提到整合Lambda和kappa架构的需求。分析规则元数据表由分析规则,情感词库组层,对应实时计算中的维表。计算系统这里选用阿里云实时流计算产品Blink,Blink是一款支持流计算和批计算一体的实时计算产品。并且类似Tablestore可以很容易的做到分布式水平扩展,让计算资源随着业务数据增长弹性扩容。使用Tablestore + Blink的优势有以下几点: Tablestore已经深度和Blink进行整合,支持源表,维表和目的表,业务无需为数据流动开发代码。整套架构大幅降低组建个数,从开源产品的6~7个组建减少到2个,Tablestore和Blink都是全托管0运维的产品,并且都能做到很好的水平弹性,业务峰值扩展无压力,使得大数据架构的运维成本大幅降低。业务方只需要关注数据的处理部分逻辑,和Tablestore的交互逻辑都已经集成在Blink中。开源方案中,如果数据库源希望对接实时计算,还需要双写一个队列,让流计算引擎消费队列中的数据。我们的架构中数据库既作为数据表,又是队列通道可以实时增量数据消费。大大简化了架构的开发和使用成本。流批一体,在舆情系统中实时性是至关重要的,所以我们需要一个实时计算引擎,而Blink除了实时计算以外,也支持批处理Tablestore的数据, 在业务低峰期,往往也需要批量处理一些数据并作为反馈结果写回Tablestore,例如情感分析反馈等。那么一套架构既可以支持流处理又可以支持批处理是再好不过。这里我们可以参考之前的一篇文章《实时计算最佳实践:基于表格存储和Blink的大数据实时计算》。一套架构带来的优势是,一套分析代码既可以做实时流计算又可以离线批处理。整个计算流程会产生实时的舆情计算结果。重大舆情事件的预警,通过Tablestore和函数计算触发器对接来实现。Tablestore和函数计算做了增量数据的无缝对接,通过结果表写入事件,可以轻松的通过函数计算触发短信或者邮件通知。完整的舆情分析结果和展示搜索利用了Tablestore的新功能多元索引,彻底解决了开源Hbase+Solr多引擎的痛点: 运维复杂,需要有运维hbase和solr两套系统的能力,同时还需要维护数据同步的链路。Solr数据一致性不如Hbase,在Hbase和Solr数据语意并不是完全一致,加上Solr/Elasticsearch在数据一致性很难做到像数据库那么严格。在一些极端情况下会出现数据不一致的问题,开源方案也很难做到跨系统的一致性比对。查询接口需要维护两套API,需要同时使用Hbase client和Solr client,索引中没有的字段需要主动反查Hbase,易用性较差。参考文献Lambda大数据架构Kappa大数据架构Lambda和Kappa架构对比总结本文基于《百亿级全网舆情分析系统存储设计》并结合Tablestore的新功能做了现代大数据舆情系统的架构升级,实现了海量信息下的实时舆情分析存储系统。也介绍了开源方案,并和我们的方案做了详细的对比。 本文作者:宇珩阅读原文 本文为云栖社区原创内容,未经允许不得转载。

June 3, 2019 · 1 min · jiezi

5分钟了解阿里时序时空数据库

简介时序时空数据库(Time Series & Spatial Temporal Database,简称 TSDB)是一种高性能、低成本、稳定可靠的在线时序时空数据库服务,提供高效读写、高压缩比存储、时序数据插值及聚合计算等服务,广泛应用于物联网(IoT)设备监控系统、企业能源管理系统(EMS)、生产安全监控系统和电力检测系统等行业场景;除此以外,还提供时空场景的查询和分析的能力。 三个数据库时序时空数据库文档最近经过几次大的变动,有点乱,看的时候注意一下。 时序数据库TSDB版 经过阿里集团大规模验证的时序数据库,支持分布式集群架构水平扩展,支持千万物联网设备接入,基于自研压缩算法,具备高效压缩比。 - 针对时序数据优化,包括存储模型,多值数据模型,时序数据压缩、聚合、采样,高效压缩算法,列存,边缘一体化;- 具备高性能,内存优先数据处理,分布式MPP SQL并行计算,动态schema,实时流式数据计算引擎,海量时间线自适应索引;- 高可扩展,数据动态分区,水平扩展,动态弹性扩容,动态升降配规格;高可靠性,自动集群控制,线程级读写分离,多层数据备份,分级存储;- 瞄准的是大规模指标数据,事件数据场景协议兼容OpenTSDB,但后面内核实现是阿里自研的。但还是完全可以把它当作OpenTSDB的阿里云版,参见 相比OpenTSDB优势 InfluxDB® 不仅仅是一个数据库,更是一个监控系统,围绕采集,可视化,分析服务,事件和指标存储和计算系统;走的是tick生态,瞄准指标,事件,trace,日志,实时分析场景。 InfluxDB®刚上线不久,现在还处在公测阶段。写入速度经测试,每次500条数据,每秒可以执行26次左右,平均速度达到1万/s,增加每次写入数据条数应该还能提高速度。另外,请求地址是外网,如果使用vpc网络速度应该还会加快不少。 注意:InfluxDB在阿里云上有时间线限制(数据库级别最高1万),时间线的定义参见后面简介。 时空数据库 时空数据库能够存储、管理包括时间序列以及空间地理位置相关的数据。时空数据是一种高维数据,具有时空数据模型、时空索引和时空算子,完全兼容SQL及SQL/MM标准,支持时空数据同业务数据一体化存储、无缝衔接,易于集成使用。 时空数据库主要是空间相关的场景,比如热力图,店铺选址等等。 时序数据库简介(主要是InfluxDB)时序数据库英文全称为 Time Series Database,提供高效存取时序数据和统计分析功能的数据管理系统。主要的时序数据库包括OpenTSDB、Druid、InfluxDB以及Beringei这四个。本人主要了解一点OpenTSDB和InfluxDB,不过时序数据库有很多共性。 基本名词 measurement: tag,field和time列的容器对InfluxDB: measurement在概念上类似于传统DB的table(表格) 从原理上讲更像SQL中表的概念,这和其他很多时序数据库有些不同对其他时序DB: Measurement与Metric等同field(数值列): TSDB For InfluxDB®中不能没有field。注意:field是没有索引的在某种程度上,可以把field理解为k/v表的valuetag(维度列): tag不是必须要有的字段tag是被索引的,这意味着以tag作为过滤条件的查询会更快在某种程度上,可以把field理解为k/v表的keytimestamp(时间戳): 默认使用服务器的本地时间戳时间戳是UNIX时间戳,单位:纳秒最小的有效时间戳是-9223372036854775806或1677-09-21T00:12:43.145224194Z最大的有效时间戳是9223372036854775806或2262-04-11T23:47:16.854775806Zpoint(数据点): 由时间线(series)中包含的field组成。每个数据点由它的时间线和时间戳(timestamp)唯一标识您不能在同一时间线存储多个有相同时间戳的数据点Series(时间线) Series是InfluxDB中最重要的概念,时序数据的时间线就是:一个数据源采集的一个指标随着时间的流逝而源源不断地吐出数据这样形成的一条数据线称之为时间线。 下图中有两个数据源,每个数据源会采集两种指标: Series由Measurement和Tags组合而成,Tags组合用来唯一标识Measurement就是说:1\. Measurement不同,就是不同的时间线2\. Measurement相同,Tags不同也是不同的时间线retention policy(保留策略,简称RP) 一个保留策略描述了: 1.InfluxDB保存数据的时间(DURATION) 2.以及存储在集群中数据的副本数量(REPLICATION) 3.指定ShardGroup Duration注:复本系数(replication factors)不适用于单节点实例。autogen:无限的存储时间并且复制系数设为1RP创建语句如下: CREATE RETENTION POLICY ON <retention_policy_name> ON <database_name>DURATION <duration> REPLICATION <n> [SHARD DURATION <duration> ] [DEFAULT]实例:CREATE RETENTION POLICY "one_day_only" ON "water_database"DURATION 1d REPLICATION 1 SHARD DURATION 1h DEFAULT写入时指定rp进行写入: ...

May 27, 2019 · 2 min · jiezi

洞见数据库前沿-集结阿里云数据库最强阵容-DTCC-2019-八大亮点抢先看

摘要: 作为DTCC的老朋友和全球领先的云计算厂商,阿里云数据库团队受邀参加本次技术盛会,不仅将派出重量级嘉宾阵容,还会为广大数据库业内人士和行业用户奉上8场精彩议题。下面小编就为大家提前梳理了8大亮点,并附上阿里云议题全集,精彩一网打尽。2019年5月8日-5月10日,由国内知名IT技术社区主办的数据库技术交流盛会——DTCC 2019将在北京新云南皇冠假日大酒店召开。数据风云,十年变迁,DTCC见证并铭记了国内数据库技术的关键成长历程。作为DTCC的老朋友和全球领先的云计算厂商,阿里云数据库团队受邀参加本次技术盛会,不仅将派出重量级嘉宾阵容,还会为广大数据库业内人士和行业用户奉上8场精彩议题,精彩不容错过。 本次DTCC大会云集多位阿里云数据库顶级大咖,将为您带来最具价值的技术交流和探讨,干货满满。由阿里巴巴集团副总裁、达摩院数据库首席科学家、阿里云智能事业群数据库产品事业部总负责 李飞飞博士领衔,Google第一代分布式SQL系统Tenzing核心人物、阿里云OLAP产品分析引擎负责人林亮,数据库内核团队资深技术专家何登成等核心团队成员将依次亮相,分别就云原生数据库、新一代自研分析型数据库、分布式数据库、时序数据库、图数据库等最in的技术话题,展开深入讨论,分享最佳实战经验。同时,李飞飞博士还将作为DTCC大会的专家顾问,把握数据技术的主题内容与方向。 洞见前沿技术趋势,见证阿里云数据库成长历程。在这场数据库领域从业人士难得的年度盛会和交流平台上,阿里云技术大牛们将带来怎样的饕餮盛宴? 下面小编就为大家提前梳理了8大亮点,并附上阿里云议题全集,精彩一网打尽。期待与您共聚一堂,共话行业未来! 温馨提示不在北京?到不了现场?没关系,我们为您准备了议题直播,欢迎点击下面的直播链接,尽情围观!5月9日-5月17日,每天下午15:00敬请锁定云栖社区直播,关注这场数据库技术干货的大咖SHOW 点击直播链接,预约观看就可领取阿里云数据库超值代金券!数量有限,先到先得哦! 亮点1:阿里云云原生数据库——我们不一样作为基础软件之一,数据库一直是企业IT系统的核心。随着云计算的到来及相关技术的不断成熟,推动了数据库行业的快速发展,传统数据库铁打的防线也正在被撕裂。 在云计算时代,云原生数据库开始崛起,通过弹性扩展、按量付费等特性获得了大量企业用户的青睐,挑战 Oracle 等传统数据库厂商的位置。在2018年,Gartner发布的数据库魔力象限中,云数据库厂商的表现极为抢眼,作为国内云计算行业的佼佼者,阿里云数据库更是跻身“远见者”象限。 为了满足弹性扩展、弹性计算、以及按需按量付费等云上应用需求,云原生数据库需要利用软硬件一体化设计,基于新兴的 RDMA、NVM 等高速硬件,研发全用户态的 IO 与网络协议栈以提供极低的延迟。 同时探索新的体系架构例如通过 shared-storage 来实现 shared-everything 和存储计算分离,提供一写多读的扩展能力。在某些高并发、对水平拓展有强需求的应用场景下,云原生数据库同时也需要探索基于 shared-nothing 的分布式架构来提供分布式数据库能力来处理分布式 SQL 查询和分布式事务处理。金融级高可用、异地多活等技术挑战也是云原生数据库所必须提供的关键能力。 演讲主题:《云时代数据库的演进》演讲嘉宾:李飞飞(花名:飞刀),阿里巴巴集团副总裁,达摩院首席数据科学家,阿里云智能事业群数据库产品事业部负责人 议题简介:阿里巴巴数据库团队自主研发的存储引擎 X-Engine 充分利用数据的冷热特性以及计算机系统结构的分层内存体系,通过冷热数据分离存储技术,提升写性能的同时降低成本。基于对以上技术挑战的不断探索和实践,阿里巴巴数据库团推出了云原生数据库 POLARDB 和其分布式版本 POLARDB-X,经受了2018年阿里巴巴双十一的交易峰值挑战并在阿里云上取得了商业化的成功。 本次分享将基于阿里云数据库近期在 VLDB,SIGMOD 上的论文内容,结合核心系统设计原理,介绍云原生数据库技术的挑战和发展趋势。 演讲时间:5月8日11:05-11:45主会场场次:主场1——数据架构 十年变迁直播时间:5月9日 15:00-16:00直播链接:https://yq.aliyun.com/live/1043?utm_content=g_1000056249亮点2:数据库内核研究,深度解码阿里数据库实现演讲主题:《POLARDB-X架构和技术演进》演讲嘉宾:何登成(花名:圭多),阿里云智能数据库产品事业部资深技术专家,DTCC的老朋友。从2005年开始一直坚守在数据库内核研发领域,先后在神州通用、网易和阿里从事数据库内核产品研发工作,目前带领团队打造阿里新一代分布式数据库POLARDB-X。 议题简介:作为阿里自研的新一代分布式数据库,POLARDB-X支撑了阿里巴巴90%以上的在线数据库应用。从AliSQL到POLARDB-X,经历了怎样的思考?在过去的一年,POLARDB-X在技术上有了哪些演进?希望能在DTCC的舞台上,跟朋友们进行深度的分享和交流。 演讲时间:5月8日16:20-17:10专场场次:数据库内核技术直播时间:5月9日 16:00-17:00直播链接:https://yq.aliyun.com/live/1045?utm_content=g_1000056250亮点3:海量数据毫秒级分析背后的架构挑战以及工程实践演讲主题:《超大规模实时数仓架构挑战与实践解析》 演讲嘉宾:林亮(花名:意博),阿里云智能数据库产品事业部研究员,曾就职Google十多年,在超大规模SQL Engine和规模存储引擎上经验丰富。目前在负责阿里云PB级分析型数据库AnalyticDB架构工作。 议题简介:数据分析领域目前正在朝着在线化方向演进,数据业务在海量数据实时写入、高并发分析、稳定性、灵活性上挑战巨大。分析型数据库AnalyticDB是阿里巴巴自主研发的超大规模PB级实时数据仓库, 近2年在上述挑战背后的技术领域稳扎稳打,做了大量的难点突破和技术创新,本次演讲深入分析AnalyticDB海量数据毫秒级分析背后的架构挑战以及工程实践。 演讲时间:5月9日09:40-10:20主会场场次:主场2——数据架构 十年变迁直播时间:5月10日 15:00-16:00直播链接:https://yq.aliyun.com/live/1047?utm_content=g_1000056251亮点4:教你解锁时序时空数据库的种种黑科技演讲主题:《阿里云TSDB: 拥抱物联网的新一代时序时空数据库》演讲嘉宾:伊翼(花名:老滚)。阿里云智能数据库产品事业部技术专家,从事TSDB核心引擎的研发工作。 议题简介:阿里云TSDB是阿里自研的一种高性能,低成本,稳定可靠的在线时序时空数据库产品。该产品统一了阿里巴巴集团90%以上的APM数据和事件型数据的存储和计算,并在广泛应用于外部的物联网,工业制造,电力,化工以及IT运维等行业。本演讲将介绍该时序时空数据库的种种黑科技:・提供千万级并发读写・双十一写入TPS达到6000万/秒・十倍以上压缩比低成本存储・PB级时序时空数据秒级聚合・每天百亿时间线的集群规模等等 演讲时间:5月8日15:50-16:30专场场次:NoSQL技术与实践直播时间:5月13日 15:00-16:00直播链接:https://yq.aliyun.com/live/1044?utm_content=g_1000056252亮点5:把握数据库发展趋势 DBA应如何避免“踩坑”?进行云时代以后,IT行业各工种的职责都在发生变化,云数据库使得日常DBA管理实现更多的自动化,大大提高日常管理效率,同时也对于企业整体投资产出可以更快获得成效。对于DBA职位的而言,当前是一个转变期,不少企业从业务开始之初就直接使用云计算。 演讲主题:《如何构建云时代DBA的知识体系》演讲嘉宾:萧少聪(花名:铁庵),阿里云智能数据库产品事业部高级产品专家,PostgreSQL中国社区常委 议题简介:如何构建云时代DBA的知识体系?通过本次演讲,希望能够协助行业中已有的DBA转型及新就业进入DBA的技术人员对云DBA加深了解,让大家在转型过程少走弯路。 云数据库 vs 传统数据库管理模式对比;云DBA知识体系构成:基础、云主机、云数据库、智能化管理;直接使用云数据库与在云主机中自建数据库的管理差异;如何成长为一名优秀的云DBA。演讲时间:5月8日11:05-11:45专场场次:云时代的数据库(上)**直播时间:5月14日15:00-16:00直播链接:https://yq.aliyun.com/live/1046?utm_content=g_1000056253亮点6:关于数据库灾备,你想知道的都在这里演讲主题:《云时代数据库迁移 & 容灾技术新进展与应用》 演讲嘉宾:付大超(花名:千震),2012年加入阿里巴巴,目前负责DTS&DBS团队和研发,在阿里云提供迁移、同步和容灾的服务,支持阿里巴巴、蚂蚁、阿里云等异地多活单元化架构,曾负责阿里全球最大的HBase集群的开发和维护工作,曾先后工作于IBM、Cisco。 议题简介:迁移&容灾是数据库的强需求,传统的迁移&容灾技术已经发展多年,随着云时代的来临,在迁移&容灾的使用场景、网络、技术都有很大的变化,如何在云时代下更简单的实现数据库的迁移&容灾,云厂商如何通过新的技术实现弯道超车,本次topic主要分享阿里云在此领域的技术新进展和应用。 演讲时间:5月9日17:10-18:00专场场次:云时代数据库(下)直播时间:5月15日15:00-16:00直播链接:https://yq.aliyun.com/live/1048?utm_content=g_1000056254亮点7:NoSQL——如何拥有居家必备的企业级能力当整个世界由IT走向DT时代,数据库领域也发生了重大变化,NoSQL已成为企业应用常态 演讲主题:《NoSQL数据库最新技术发展趋势》 演讲嘉宾:朱洁(花名:所在),阿里云智能数据库产品事业部高级产品专家,当前为阿里云数据库NoSQL数据库产品Leader。10+数据库/大数据研发管理经验,专注于数据库/大数据服务平台建设、规划和实践应用,著有畅销书《大数据架构详解:从数据获取到深度学习》。 议题简介:企业IT系统面临层出不穷的新业务,安全,成本等诸多挑战。阿里云NoSQL数据库通过与企业业务深度结合,快速创新,提供最新的技术帮助企业用户迎接挑战,获得金融、社交、直播等众多大客户的信任。 本次演讲重点介绍阿里云NoSQL数据库在全球分布式,多模,弹性,HTAP,cloudNative,图,时序,时空等众多最新领域的创新和技术实践。 演讲时间:5月10日 09:40-10:20专场场次:分布式数据库实践(下)直播时间:5月16日15:00-16:00直播链接:https://yq.aliyun.com/live/1049?utm_content=g_1000056255亮点8:前沿技术应用——图数据库知多少?数据库从业者必看演讲主题:《探索互联数据的奥秘——图数据库GDB》 演讲嘉宾:王炎(花名:夜炎),阿里云智能数据库产品事业部高级技术专家。在分布式系统、存储领域以及NoSQL系统研发领域经验丰富。18年加入阿里巴巴集团,现在阿里负责图数据库系统相关研发工作。 ...

May 8, 2019 · 1 min · jiezi

阿里巴巴支付宝员工都在用的知识管理工具究竟有何特别

公司内各部门工作文档难以共享?缺乏高效便捷的团队协作工具?文档放到在线云平台担心安全?…… 2019年4月22日,蚂蚁金服旗下知识创作与分享工具语雀发布“空间功能”。语雀在支持在线文档编写、多人协作、灵活的团队管理和金融级安全存储的基础上,新增“空间”功能,助力企业知识管理,帮助企业快速提升团队内容协作与知识管理效率,同时搭建企业知识门户,系统沉淀企业数据资产。 语雀是蚂蚁金服体验科技研发的创新产品,目前已是阿里员工进行文档编写、知识沉淀、搭建组织知识库的标配。 便捷的在线文档编辑基于蚂蚁金服体验技术的实践积累,语雀采用了自主研发的文档编辑器,不仅便捷易用,响应迅速,还支持文档分享及多样化的编辑功能。同时,语雀还具备实时云储存功能,编辑过程中可进行自动保存。 当文档编辑完成后,你可以通过在线的形式,或将文档导出为Word、PDF等本地文件来分享给朋友或者同事。如果希望非团队成员参与文档的编辑,可以使用文档的分享功能来解决。 而历史版本管理功能,可以查阅历史编辑的每一个版本。工作中一个文档的最终完成常常需要多人参与,到最后容易混淆,而通过文档分享功能和历史版本管理可以轻松解决文档版本管理问题。 金融级安全实时存储依托于蚂蚁金服支付宝底层技术,语雀信息存储具备金融级安全属性,对数据采用了双重密钥加密存储确保数据安全,同时文档发布可历史永久保存确保永不丢失、完整的操作日志方便团队危险操作有迹可循。 除此之外,语雀还获得了ISO安全认证和公安部三级等级保护认证。 “空间”:灵活的企业团队和知识体系管理语雀空间是面向企业或组织推出的全新知识管理方式,在这里你可以实现知识在线化管理,与成员一起交流分享知识。 语雀“空间”功能支持灵活的团队管理,除了自己手动建立团队,还支持钉钉等平台的团队导入。 知识文档管理方面,语雀支持结构化知识归档管理,通过文档大纲,自动生成文档要点,使用知识库目录编排,让多篇文档结构化,形成一本本像书一样清晰易读的知识库。 于企业机构而言,语雀提供了全新的体系化知识管理,帮助企业让协作更高效,让知识成为企业财富。 以云谷学校为例,在语雀中,云谷学校创建了许多团队,「智库」是其中之一。“智库”是云谷学校教育科学研究院搭建的一个内部分享平台,是云谷“科研扁平化”的尝试:每一个老师都是智库的主人,可以在这里建立自己的小平台,展示自己正在研究和探索的领域及进展;它也是开放和互动的,希望通过把自己向其他人打开:“把自己的研究暴露在大家的监督下,把自己的探索暴露在大家的帮助下,让自己的能力暴露在那些可以发起协作的人的面前。” 在“智库”有研究院搜集整理的一些教育理论与方法,也有老师们自发分享的自己的推荐和研究内容,也有技术部门、HR部门建立的工具平台,让云谷的所有人更好地熟悉云谷已经走过的路。 学校的老师们表示,语雀知识库不仅有利于学校的知识沉淀,也有利于教师团队工作的展开。 目前,语雀“空间功能”已正式上线,点击官网即可开通体验。体验地址:https://yuque.com。 本文作者:华蒙阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 28, 2019 · 1 min · jiezi

你应该知道的 HBase 基础,都在这儿了

阿里妹导读:2006 年10 月Google 发布三架马车之一的《Bigtable:A Distributed Storage System for Strctured Data》论文之后,Powerset 公司就宣布 HBase 在 Hadoop 项目中成立,作为子项目存在。后来,在2010 年左右逐渐成为 Apache 旗下的一个顶级项目。可能是实际应用中包装得太好,很多人对于 HBase 的认识止步于 NoSQL 。今天,蚂蚁金服的南俊从基础开始讲起,希望有助于增强大家在实际业务中对 HBase 的理解。一、 HBase 简介 HBase 名称的由来是由于其作为 Hadoop Database 存在的,用来存储非结构化、半结构化数据。 要想知道 HBase 的用途,就需要看一看其在 Apache 的 Hadoop 生态系统中的位置,可以看到 HBase 是构建在 HDFS 之上的,这是由于 HBase 内部管理的文件全部都是存储在 HDFS 当中的。同时,MapReduce 这个计算框架在 HBase 之上又提供了高性能的计算能力来处理海量数据。此外还有一些像 Pig、Hive 用来提供高层语言的支持。还有 Sqoop 用来完成传统数据库到 HBase 之间的数据迁移。类似衍生出来的新技术还有很多,有兴趣的同学可以自己去了解一下。 Google 的三架马车 BigTable、GFS、MapReduce 现在在开源社区中都能找到对应的实现。HBase 就是 Bigtable 的开源实现,当然这句话不是完全正确,因为两者之间还是有些差异的。但是主要还是基于 BigTable 这个数据模型开发的,因此也是具有 Key-Value 特征的,同时也就具有 Bigtable 稀疏的、面向列的这些特性。 ...

April 22, 2019 · 1 min · jiezi

基于TableStore的海量气象格点数据解决方案实战

前言气象数据是一类典型的大数据,具有数据量大、时效性高、数据种类丰富等特点。气象数据中大量的数据是时空数据,记录了时间和空间范围内各个点的各个物理量的观测量或者模拟量,每天产生的数据量常在几十TB到上百TB的规模,且在爆发性增长。如何存储和高效的查询这些气象数据越来越成为一个难题。传统的方案常常采用关系型数据库加文件系统的方式实现这类气象数据的存储和实时查询,这种方案在可扩展性、可维护性和性能上都有一些缺陷,随着数据规模的增大,缺点越来越明显。最近几年,业界开始越来越多的基于分布式NoSQL来解决这一问题,比如基于TableStore来实现气象格点数据的存储和查询。TableStore是一款阿里自研的分布式NoSQL服务,可以提供超大规模的存储容量,支撑超大规模的并发访问和低延迟的性能,可以很好的解决气象数据的规模和查询性能问题。我们之前也写过相关的解决方案文章《基于云上分布式NoSQL的海量气象数据存储和查询方案》,也有一些客户基于这个方案进行了开发。出于减少客户开发难度,提供通用的实现的想法,我们最近开发了一个TableStore-Grid的Library,基于这个Library用户可以非常方便的实现气象格点数据的存储、查询和管理。本文作为一个实战文章,主要讲解这一解决方案的设计以及使用方式。背景格点数据的特点格点数据具有明显的多维特点,以模式系统每次产生的数据为例,一般包含以下五个维度:物理量,或者称为要素:温度、湿度、风向、风速等等。预报时效:未来3小时、6小时、9小时、72小时等等。高度。经度。纬度。当我们固定某一要素某一预报时效,那么高度、经度、纬度就构成一个三维网格数据,如下图所示(图片来自互联网)。每个格点代表了一个三维空间上的点,上面的数值为该点在某一预报时效(比如未来三小时)下,某一物理量(比如温度)的预报值。假设一个三维格点空间包含10个不同高度的平面,每个平面为一个2880 x 570的格点,每个格点保存一个4字节数据,那么这三维的数据量为2880 x 570 x 4 x 10, 大约64MB。这仅仅是某个模式系统对某个物理量某一时效下的一次预报,可见模式数据的总量是非常大的。格点数据的查询方式预报员会通过页面的形式浏览各种模式数据(格点数据),并进行数值模式预报。这个页面需要提供多种模式数据的查询方式,比如:查询一个经纬度平面的格点数据:比如未来三小时全球地面温度的格点数据,或者未来三小时浙江省地面温度数据。查询某个格点的时间序列数据:比如阿里云公司所在地未来3小时、未来6小时、一直到未来72小时的温度。查询不同物理量的数据:比如查询某一预报时效、某一高度、某一点的全部物理量的预报数据。查询不同模式系统产生的数据:比如同时查询欧洲中心的某一模式数据和中国气象机构产生的对应数据等。上面提到,一个格点数据集一般是一个五维结构,各种查询方式实际上就是对这个五维数据进行切分,比如查询某个平面,每个剖面,某个点序列,某个三维、四维子空间等等。而我们的方案设计要保证在各种查询条件的查询性能,这是数据查询方面的主要技术难点。基于TableStore的方案设计标准化格点数据模型首先,我们定义一个规整的五维网格数据为一个GridDataSet,表示一个格点数据集,按照维度顺序,其五维分别为:variable:变量,比如各种物理量。time:时间维度。z: z轴,一般表示空间高度x: x轴,一般表示经度或纬度。y:y轴,一般表示经度或纬度。GridDataSet = F(variable, time, z, x, y)。一个GridDataSet除了包含五维数据,以及各个维度的长度等外,还包含一些其他信息:GridDataSetId:唯一标记这个GridDataSet的Id。Attributes:自定义属性信息,比如该数据的产生时间、数据来源、预报类型等等。用户可以自由定义自定义属性,也可以给某些属性建立索引,建立索引后就可以通过各种组合条件来查询符合条件的数据集。举个例子来说,假设某种气象预报,每次预报未来72小时的每个整点的各个高度、各个经纬度的各种物理量,则这次预报就是一个标准的五维数据,是一个单独的数据集(GridDataSet),下一次相同的预报则是另一个数据集,这两个数据集需要有不同的GridDataSetId。这两个数据集比较类似,只是起报时间不同,但是因为起报时间不在五维模型中(五维内的时间为一次预报中的未来不同时刻),所以属于不同的数据集,起报时间可以作为数据集的自定义属性。本方案中,也支持对自定义属性设置条件进行检索。数据存储方案我们设计了两张表分别存储数据集(GridDataSet)的meta和data,meta表示这个数据集的各种元数据,比如GridDataSetId、各维度长度、自定义属性等等,data表示这个数据集里实际的网格数据。data相比meta在数据大小上要大很多。为什么要分为meta和data两张表分开存储,主要是出于这样的考虑:用户会有根据多种条件查询数据集的要求,比如查询最近有哪些数据集已经完成入库,或者查询表中有哪些某种类型的数据集等。传统方案中主要是通过MySQL等关系型数据库来存储,在本方案中我们通过单独的meta表来存储,并通过TableStore的多元索引功能来实现多条件的组合查询和多种排序方式,相比传统方案更加易用。在查询格点数据之前,一般要知道格点数据中各维度的长度等信息,这些信息就是存储在meta表中的,即需要先查询meta表,再查询data表。因为meta数据一般都很小,因此查询效率相比查询data要高,多一次查询并不会明显增加延迟。meta表设计meta表的设计比较简单,主键只有一列,记录GridDataSetId,因为GridDataSetId就可以唯一标记一个GridDataSet。各种系统属性和自定义属性保存在meta表的属性列中。查询meta表有两种方式,一种是通过GridDataSetId直接查询,另外一种是通过多元索引,可以根据多种属性条件组合进行查询,比如筛选某种类型的数据,按照入库时间从新到老返回等。data表设计data表的设计要解决五维数据在不同的切分模式下的查询效率问题,不能简单直接的对数据进行存储。首先,为了查询效率最高,我们要尽量减少一次查询需要扫描的数据量。一个数据集的数据量可能在几GB的级别,但是一次查询往往只需要其中的几MB的数据,如果无法高效的定位要查询的数据,那么就要扫描全部的几GB的数据,从中筛选出符合某个范围的数据,显然效率是很低的。那么怎么才能做到高效的定位到需要的数据之中呢?我们首先设计一种表结构设计方式,我们使用四列主键列,分别为:GridDataSetId:数据集Id,唯一标记这个数据集。Variable:变量名,即五维模型中的第一维。Time:时间,即五维模型中的第二维。Z:高度,即五维模型中的第三维。这四列主键列标记一行TableStore中的数据,这行数据需要保存后两维的数据,即一个格点平面。这种设计下,对于五维中的前三维,我们都可以通过主键列的值来定位,即对于前三维的每一种情况,都对应TableStore中的一行。因为前三维分别代表变量、时间和高度,一般而言不会特别的多,每个维度在几个到几十个的级别,我们可以通过一些并行查询的方法来加速查询速度。剩下的问题就在于后两维数据如何存储和查询。首先后两维代表了一个水平的平面,一般是一个经纬度网格,这两维的大小是比前三维要大很多的,每维在几百到几千的级别,随着数值预报越来越精细化,这个网格的大小还会成倍增加。这样的一个稠密的网格数据,我们不能把每个格点都用一列来保存,这样列的数量会非常多,存储效率也会非常的低。另一方面,如果我们把一个平面的格点数据存储到一列中,在整读整取时效率比较高,但是如果只读取某个点,就会读取很多的无效数据,效率又会变得比较低。因此我们采取一种折中的方案,对平面的二维数据再次进行切分,切分成更小的平面数据块,这样就可以做到只读取部分数据块,而不总是读取整个平面,因此极大的提高了查询性能。方案实现基于上面的存储方案,我们实现了一个TableStore-Grid的library,提供以下接口:public interface GridStore { /** * 创建相关的meta、data表,数据录入前调用。 * @throws Exception / void createStore() throws Exception; /* * 写入gridDataSet的meta信息。 * @param meta * @throws Exception / void putDataSetMeta(GridDataSetMeta meta) throws Exception; /* * 更新meta信息。 * @param meta * @throws Exception / void updateDataSetMeta(GridDataSetMeta meta) throws Exception; /* * 通过gridDataSetId获取meta。 * @param dataSetId * @return * @throws Exception / GridDataSetMeta getDataSetMeta(String dataSetId) throws Exception; /* * // 创建meta表的多元索引。 * @param indexName * @param indexSchema * @throws Exception / void createMetaIndex(String indexName, IndexSchema indexSchema) throws Exception; /* * 通过多种查询条件来查询符合条件的数据集。 * @param indexName 多元索引名。 * @param query 查询条件,可以通过QueryBuilder构建。 * @param queryParams 查询相关参数,包括offset、limit、sort等。 * @return * @throws Exception / QueryGridDataSetResult queryDataSets(String indexName, Query query, QueryParams queryParams) throws Exception; /* * 获取GridDataWriter用于写入数据。 * @param meta * @return / GridDataWriter getDataWriter(GridDataSetMeta meta); /* * 获取GridDataFetcher用于读取数据。 * @param meta * @return / GridDataFetcher getDataFetcher(GridDataSetMeta meta); /* * 释放资源。 / void close();}public interface GridDataWriter { /* * 写入一个二维平面。 * @param variable 变量名。 * @param t 时间维的值。 * @param z 高度维的值。 * @param grid2D 平面数据。 * @throws Exception / void writeGrid2D(String variable, int t, int z, Grid2D grid2D) throws Exception;}public interface GridDataFetcher { /* * 设置要查询的变量。 * @param variables * @return / GridDataFetcher setVariablesToGet(Collection<String> variables); /* * 设置要读取的各维度起始点和大小。 * @param origin 各维度起始点。 * @param shape 各维度大小。 * @return / GridDataFetcher setOriginShape(int[] origin, int[] shape); /* * 获取数据。 * @return * @throws Exception */ GridDataSet fetch() throws Exception;}下面我们分别给出数据录入、数据查询、数据集检索方面的示例。数据录入数据录入流程可以分为三部分:写入putDataSetMeta接口写入数据集的meta信息。通过GridDataWriter录入整个数据集的数据。通过updateDataSetMeta接口更新数据集的meta信息,标记数据已经录入完成。下面的例子中,我们读取一个NetCDF(气象格点数据常用的格式)文件,然后将其中的数据通过GridDataWriter录入到TableStore中。通过GridDataWriter每次写入时,只能写入一个二维平面,所以我们需要在外层进行3层循环,分别枚举变量维、时间维、高度维的值,然后读取对应的二维平面的数据进行录入。public void importFromNcFile(GridDataSetMeta meta, String ncFileName) throws Exception { GridDataWriter writer = tableStoreGrid.getDataWriter(meta); NetcdfFile ncFile = NetcdfFile.open(ncFileName); List<Variable> variables = ncFile.getVariables(); for (Variable variable : variables) { if (meta.getVariables().contains(variable.getShortName())) { for (int t = 0; t < meta.gettSize(); t++) { for (int z = 0; z < meta.getzSize(); z++) { Array array = variable.read(new int[]{t, z, 0, 0}, new int[]{1, 1, meta.getxSize(), meta.getySize()}); Grid2D grid2D = new Grid2D(array.getDataAsByteBuffer(), variable.getDataType(), new int[] {0, 0}, new int[] {meta.getxSize(), meta.getySize()}); writer.writeGrid2D(variable.getShortName(), t, z, grid2D); } } } }}数据查询GridDataFetcher支持对五维数据进行任意维度的查询。第一维是变量维,通过setVariablesToGet接口设置要读取哪些变量,其余四维通过设置起始点(origin)和读取的大小(shape)就可以实现任意维度读取。public Array queryByTableStore(String dataSetId, String variable, int[] origin, int[] shape) throws Exception { GridDataFetcher fetcher = this.tableStoreGrid.getDataFetcher(this.tableStoreGrid.getDataSetMeta(dataSetId)); fetcher.setVariablesToGet(Arrays.asList(variable)); fetcher.setOriginShape(origin, shape); Grid4D grid4D = fetcher.fetch().getVariable(variable); return grid4D.toArray();}多条件检索数据集本方案中,对Meta表建立多元索引后,可以支持通过各种组合条件来进行数据集检索,查询出符合条件的数据集,这个功能对于气象管理系统来说非常重要。下面举一个例子,假设我们要查询已经完成入库的,创建时间为最近一天的,来源为ECMWF(欧洲中期天气预报中心)或者NMC(全国气象中心),精度为1KM的气象预报,并按照创建时间从新到老排序,可以用以下代码实现:查询条件: (status == DONE) and (create_time > System.currentTimeMillis - 86400000) and (source == “ECMWF” or source == “NMC”) and (accuracy == “1km”)QueryGridDataSetResult result = tableStoreGrid.queryDataSets( ExampleConfig.GRID_META_INDEX_NAME, QueryBuilder.and() .equal(“status”, “DONE”) .greaterThan(“create_time”, System.currentTimeMillis() - 86400000) .equal(“accuracy”, “1km”) .query(QueryBuilder.or() .equal(“source”, “ECMWF”) .equal(“source”, “NMC”) .build()) .build(), new QueryParams(0, 10, new Sort(Arrays.<Sort.Sorter>asList(new FieldSort(“create_time”, SortOrder.DESC)))));是不是非常简单?这一部分功能利用了TableStore的多元索引,多元索引可以实现多字段组合查询、模糊查询、全文检索、排序、范围查询、嵌套查询、空间查询等功能,给元数据管理场景提供了强大的底层能力。相关代码的获取可以在github上获取TableStore-Grid的实现代码和示例代码,欢迎大家体验、使用以及给我们提出建议。代码链接: https://github.com/aliyun/tablestore-examples/tree/master/demos/TableStore-Grid本文作者:亦征阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 16, 2019 · 2 min · jiezi

数据归档那些事儿

在热点账户问题和常用解决方案【中】这篇文章中提到,解决热点读性能的一个非常通用方式是数据归档。本篇小拽总结下在操作数据归档过程中遇到的一些问题和经验!一、数据归档所谓数据归档就是把部分低频访问的历史数据从线上库迁移到归档库的过程。在设计数据归档方案的时候通常需要思考三个问题归档前:如何进行存储选型归档中:如何保证迁移准确归档后:如何处理数据完整性破坏所引起的问题下面也着重从这三部分来聊聊二、存储选型存储选型是归档前要做的最重要的一件事情,目前市面上的存储方式多如牛毛,如何选择能够支撑当前业务环境的存储选型,就非常重要!2.1 归档的数据特点既然是要选型数据归档的存储,首先来需要梳理下归档数据的特点读性能:归档数据对读性能没啥要求,能够读出来就可以写性能:尽可能好的批量写入性能,能够批量1w+达标压缩比:尽可能的节省空间,采用高压缩比的存储引擎分布式:最好能够分布式,考虑到目前单片都40T了,非分也可数据量级:上限尽可能高,考虑到实际情况,10TB+目前达标一致性保证:归档是兜底,尽可能高的保证数据不会出现异常丢失2.2 通用选型因素除了考虑归档数据的特点,还要考虑一些通用因素,例如公司是否运维支持:大厂这个因素很重要,如果运维支持背书,最好不过!开源活跃程度:活跃度太低不能选普遍使用场景:跳出存储给的通用场景的不能选2.3 备选存储的特性也初步总结和梳理了下可能用到的集中存储的特性结合归档数据的特点和不同存储的优势,最终选用了rocksDB:作为存储归档数据引擎,性能和数据压缩比都不错,最主要是公司DBA愿意支持ES:作为在线查询,公司运维支持HIVE:作为财务数仓核心数据和全量数据中心,哈哈,为下一篇财务数据中台做铺垫^_^fusion:作为幂等健破坏后的幂等健KV池三、一致性保证归档过程存在会删除线上数据,是个非常高危的操作,所以操作过程中和操作之后都需要特别注意数据一致性的保证。对于操作过程的一致性保证相对简单,过程通常两步step1 插入确认:查询线上库->插入归档库->查询归档库->确认插入step2 删除确认:删除线上库->查询线上库->确认删除注意:过程中尽可能的保证读取和写入的时间,删除会锁库,大批量读会抢网络和IO,防止对线上业务造成压力,尽可能调优批量数据,推荐条目在200-1000条一次,数据量在5M-100M一次四、归档后问题数据归档后,必然破坏了数据的完整性,会造成下面几个问题,,需要提前考虑4.1 读数据穿透问题低频历史数据归档后,造成线上数据缺失,查询数据穿透和范围关系查询损失都会存在。因此,数据归档后,对于读操作有两种处理方式归档数据不读:最简单,但是对于某些场景可能确实不太合适。读proxy兼容:通过读proxy,穿透性的选择各种存储截止。针对读数据,还有一种比较特殊的情况,就是跨区间范围关系聚合,这样就需要有一份完整数据来满足极端需求,目前财务系统对于这类需求统一走离线财务数仓来解决!4.2 写幂等破坏问题对于写数据最大的问题就是幂等健被破坏,归档了数据后,rds写入唯一健破坏,在极端情况下,可能会造成duplicate。考虑到问题的出现概率和实现成本,初期可以忽略,采用人工干预的方式,归档最终要写入全量,写不进去就是duplicate了;后面可以采用前置幂等健组来挡,做到最终一致!4.3 数据一致性问题无论是数仓数据还是归档数据,作为财务数据,一旦提供资金服务,那么就必须保证强一致性,财务目前采用离线分天统计数据的金额和数量,来保证宏观上的一致性。这里面也有需要小坑,例如数据飘移,时间gap等,关于财务数仓中遇到的坑和解决方案,后续专项讨论五、最终归档方案分析了归档前选型,归档中数据转移,归档后数据完整性问题,初步的归档方案如下图简单梳理下核心流程写数据流:写数据写入online rds[备注:目前没有前置幂等拦截,后面择机完善],写入后通过binlog准实时写入es,提供线上读服务;通过binlog小时级入hive,作为分析数据和全量数据存储;通过天级归档脚本,将历史数据导入rocksdb归档。同时,如果有日切,也会天级进行数据日切和新表创建。读数据流:读数据过proxy,非归档期间数据直接读取es,归档数据和es没有的数据都会穿透到rocksdb。监控流:天级监控hive,es,rocksdb,三个不同来源的数据条目和总金额,保证一致性。六、总结和不足本篇主要总结了小拽在数据归档过程中,如何选型,如何归档以及在归档数据后引起的问题如何处理。通过数据归档,更清楚的划定了不同存储介质的功能边界,是进行数据中台搭建,赋能业务的前置准备!【转载请注明:数据归档那些事儿 | 靠谱崔小拽 】

April 3, 2019 · 1 min · jiezi

数据科学家为什要用Git?怎么用?

摘要:也许你在别的地方听说过Git。也许有人告诉过你,Git只适合软件开发人员。如果你是数据科学家,那么Git其实对你很重要。本文作者希望能够通过经验分享让你了解Git的重要性,以及如何在你的数据科学工作中使用它。什么是Git?Git是一个分布式版本控制系统,用于在软件开发期间跟踪源代码的更改。看看维基百科给出的这个定义,好像Git专门是为软件开发人员而设计的。实际上,Git是当今世界上使用最广泛的现代版本控制系统,它是以分布式的协作方式为项目(开源或商业)做出了伟大的贡献。除了分布式版本控制系统之外,Git的还考虑了性能、安全性和灵活性。现在你已经了解了Git是什么,但是你脑海中的问题可能是,“如果我是做数据科学项目的人,它与我的工作有什么关系?”以前我也一样不能理解Git的重要性,直到我开始在现实工作环境中,我才发现它时如此重要!为什么是Git?我们来谈谈为什么?一年前,我决定学习Git。我在Github上分享并发布了我的代码,这是我在CERN的论文项目。虽然很难理解Git中常用的术语(git-add、commit、push、pull等),但我知道这在数据科学领域很重要,这使我的数据科学工作比以往任何时候都更加充实。所以我保持学习状态,并坚持“committing”。当我加入我目前的公司时,我在Git方面的经验就派上了用场,因为Git是跨不同团队进行代码开发和协作的主要方式。更重要的是,当你的组织遵循敏捷软件开发框架时,Git尤其有用,在该框架中,Git的分布式版本控制使整个开发工作流更加高效、快速且易于适应变化。那么什么是版本控制呢?版本控制是一个系统记录一个文件或一组文件随时间的变化,以便你以后可以调用特定的版本。比如说,你是一个数据科学家,与一个团队合作,在这个团队中你和另一个数据科学家在构建机器学习模型的时候,对同一个特征进行工作。如果你对该特征做了一些更改并上传到远程存储库,并且这些更改与主分支合并,那么你的项目现在变成了1.1版本。另一位数据科学家也对版本1.1的相同功能进行了一些更改,新的更改现在与主分支合并。模型就变成1.2版本。在任何时候,如果你的团队发现版本1.2在发布期间有一些错误,他们随时可以调用以前的版本1.1,这就是版本控制的美妙之处。作为数据科学家如何使用Git?我们已经讨论过什么是Git及其重要性。现在的问题归结为:作为数据科学家如何使用Git?作为数据科学家,你不需要成为一个Git领域的专家。关键是要理解Git技术的工作流程以及如何在日常工作中使用Git。准确地说,我在这里使用的是Git Feature Branch Workflow,它通常被开源和商业项目使用。如果你想更多地了解这里使用的术语,点击这里进行了解。Git Feature Branch WorkflowFeature Branch Workflow像一个中央存储库,master分支代表正式的项目历史记录。开发人员每次开始处理一个新特性时,都会创建一个新的分支,而不是直接提交到他们的本地主分支上。新的分支可以(也应该)推送到中央存储库。在这种情况下,可以在不修改master分支的情况下与其他开发人员共享一个该分支。在开始执行任何操作之前,请键入git remote -v以确保工作区指向要使用的远程存储库。1、从主分支开始,创建一个新分支git checkout mastergit pullgit checkout -b branch-name如果总是维护和更新主分支,则切换到本地主分支,并将最新的提交和代码提取到本地主分支。假设你希望创建一个本地分支,向代码中添加一个新功能,并稍后上传到远程存储库。一旦你将最新的代码更新到本地master分支,我们就创建并checkout出一个名为branch-name的新分支,所有的更改都将在此本地分支上进行。这意味着你本地的master分支不会受到任何影响。2、更新、添加、提交并将更改推送到远程存储库git statusgit add <your-files>git commit -m ‘your message’git push -u origin branch-name上面我们做了很多操作,让我们详细了解它。一旦发生了一些更新,就将新的操作add到本地分支,并且希望将该操作上传到远程分支,以便合并到远程主分支。git status将输出你对文件的所有更改(跟踪或未跟踪)。在使用git commit-m“your message”提交消息更改之前,你将使用git add <your files>决定要暂存哪些文件。在此阶段,你的更改仅显示在本地分支中。为了使你的更改显示在BitBucket上的远程分支中,你需要使用git push -u origin branch-name命令进行提交。此命令将该分支推送到中央存储库,并且-u表示将其添加为远程跟踪分支。在设置了跟踪分支之后,可以在没有任何参数的情况下调用git push,以自动将新的功能分支推送到BitBucket上的中央存储库。3、创建pull请求现在你已经成功地添加了一个新功能并推送到远程分支。你为自己的贡献感到骄傲,你希望在将远程分支与远程主分支合并之前得到团队成员的反馈。在该分支合并到主分支之前,让其他团队成员有机会对其进行审查。你可以在BitBucket上创建pull请求。现在,你的团队成员已经查看了你的代码,并决定在代码可以合并到主代码库-master分支之前,需要你进行一些其他更改。git statusgit add <your-files>git commit -m ‘your message’git push现在,你可以按照与之前相同的步骤进行更改、提交并最终将更新推送到中央存储库。一旦使用了git push,你的更新将自动显示在pull请求中。如果其他人已将目标更改为你所接触的同一代码,则会发生合并冲突,这在工作中很常见。你可以在这里看到如何解决合并冲突。一旦一切顺利完成,这些功能将会合并到master分支中。当我第一次开始学习Git时,我感到非常沮丧,因为我仍然没有真正理解工作流。这也是写这篇文章的主要原因之一,它真正分解并在更高层次的理解上向你解释工作流程。因为我相信,对工作流程中发生的事情有一个清晰的了解将使学习过程更加有效。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 25, 2019 · 1 min · jiezi

一文纵览自然语言生成的发展

摘要: 从马尔科夫链到Transformer,本文带您纵览自然语言生成的发展。人们对人工智能的兴趣随着科幻电影的诞生和发展变得愈发浓厚。每当我们听到“人工智能”这个词,便会联想到《终结者》、《黑客帝国》、《我,机器人》等电影。机器人具有独立思考的能力在目前看来还比较遥远,但机器学习和自然语言理解领域已经在过去几年取得了重大进展。个人助理(Siri/Alexa)、聊天机器人及问答机器人等应用程序正悄无声息地改变着人们的生活方式。人们需要理解大量有歧义且结构多变的语言并从中获取意义,这促使自然语言理解(Natural Language Understanding,NLU)和自然语言生成(Natural Language Generation, NLG)成为人工智能中发展最快的应用。Gartner预测,“到2019年,自然语言生成将是90%的现代BI和分析平台的标准特征”。本文将回顾NLG的历史,并展望其未来。什么是NLG?NLG通过预测句子中的下一个单词传达信息。使用语言模型能够预测下一个可能出现的单词,也就是找到单词在序列中的概率分布。举个例子,预测“I need to learn how to __”的下一个单词,语言模型会计算下一个单词,如“write”,“drive”可能出现的概率。RNNs及LSTMs等高级神经网络能够处理较长的句子,提高了语言模型预测的准确性。马尔可夫链(Markov Chains)马尔可夫链是最早用于语言生成的算法。它通过当前单词预测句子中的下一个单词。举个例子,模型通过下面两个句子进行训练,“I drink coffee in the morning”和“I eat sandwiches with tea”。“drink”后面出现“coffee”的概率是100%,“I”后面出现“eat”和“drink”的概率分别为50%。马尔可夫链在计算下一个单词出现概率的时候,会把每个单词之间的关系考虑进去。该模型最早用于为智能手机输入句子提供下一个单词生成建议。但由于仅注意当前单词,马尔可夫模型无法探测当前单词与句子中其它单词的关系以及句子的结构,使得预测结果不够准确,在许多应用场景中受限。循环神经网络(Recurrent Neural Network, RNN)神经网络启发于人类大脑的工作原理,通过对输入和输出数据之间的非线性关系进行建模,为计算提供了一种新的方法,用于语言建模即称为神经语言建模。RNN是神经网络的一种,它能够捕捉输入数据的序列特征。通过前馈网络处理序列中的每一个item,并将模型的输出作为序列的next item,此过程能够帮助存储前面每步的信息。这样的“记忆”使得RNN在语言生成中有着出色的表现,因为记住过去的信息能够帮助更好的预测未来。与马尔可夫链不同的是,在进行预测时,RNN不仅关注当前单词,还关注已经处理过的单词。利用RNN进行语言生成在RNN的每一次迭代中,模型都能在其“记忆”单元中存储出现过的单词,以及计算下一个单词出现的概率。举个例子,有“We need to rent a __”,此时要预测句子中的下一个单词。模型能够记住在词典中每个单词随前面单词出现的概率。在上述例子中,“house”或者“car”比“river”和“dinner”有着更高的出现概率。“记忆”单元选择概率更高的单词,并对其进行排序,然后进行下一次迭代。但RNN有一个很大的问题——梯度消失。随着序列长度的增加,RNNs不能存储那些很久前遇到的单词,便只能根据最近的单词进行预测。这使得RNNs无法应用于生成连贯的长句子。长短期记忆网络(Long Short-Term Memory, LSTM)长短期记忆网络是RNNs的变体,比vanilla RNNs更适合处理长序列。LSTM应用广泛,其与RNNs的结构类似。不同的是,RNNs只有一个简单的层结构,而LSTM内部有4个层结构。一个LSTM由4部分组成:cell,输入门,输出门以及遗忘门。利用LSTM进行语言生成示例,输入句子为“I am from Spain. I am fluent in ___”。为了正确预测出下一个单词“Spanish”,LSTM会更加关注上一句中的“Spain”并且利用cell对其进行记忆。在处理序列时cell会对获取的信息进行存储,这些信息会用于预测下一个单词。当遇到句号时,遗忘门会意识到句子中的上下文发生了改变,并忽略当前cell中存储的状态信息,换句话说,遗忘门的作用是让循环神经网络“忘记”之前没有用到的信息。LSTM及其变体能够解决梯度消失问题并生成连贯的句子。但是,LSTM也有其局限性:计算要求高,难以训练。TransformerTransformer在2017年,由Google团队在论文《Attention Is All You Need》中首次提出,并涉及到一种名为“self-attention mechanism”的新方法。Transformers目前广泛用于解决NLP问题,例如语言建模,机器翻译以及文本生成等。Transformer模型由一组编码器和一组解码器组成,前者负责处理任意长度的输入,后者负责输出生成的句子。在上述示例中,编码器处理输入句子,并为其生成表示。解码器利用表示生成用于输出的句子。每个单词最初的表示或嵌入由空心圆表示。接下来,Transformer模型利用self-attention机制获取所有其他单词之间的关系,生成每个单词的新表示,如图中的实心圆。对每个单词重复该步骤,连续生成新的表示,类似地,解码器从左往右依次生成单词。与LSTMs不同的是,Transformer需要的步骤少,应用self-attention机制能够在不考虑单词位置的情况下,直接捕捉句子中所有单词之间的关系。最近,许多研究学者对vanilla transformer模型进行了改进,提升了速度与精度。在2018年,谷歌提出BERT模型,此模型在各种NLP任务中均取得了最先进的结果。在2019年,OpenAI发布了一个基于transformer的语言模型,只需要输入几行文本就可以生成长篇文章。利用Transformers进行语言生成Transformer模型同样可以用于语言生成,最著名的要数OpenAI提出的GPT-2语言模型。该模型通过将注意力集中在与预测下一个单词相关的单词上,更好的学习并预测句子中的下一个单词。使用Transformer进行文本生成与机器翻译所遵循的结构类似。举个例子,“Her gown with the dots that are pink, white and ____”。通过利用self-attention机制对前面所出现的颜色(白色和粉色)进行分析,理解需要预测的单词也是一种颜色,此时模型的输出为“blue”。Self-attention能够帮助模型选择性地关注每一个单词在句子中担任的角色,而不仅仅是通过循坏记住些许特征。语言生成的未来本文带我们纵览了语言生成的发展,从利用马尔可夫链预测下一个单词,到使用self-attention生成连贯的文章。但是,我们仍处于生成语言建模的初期,今后还会往自主生成文本的方向迈进。生成模型也将用于图像、视频、音频等内容的开发。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 25, 2019 · 1 min · jiezi

Pod在多可用区worker节点上的高可用部署

一、 需求分析当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用区,已达到高可用或者同城灾备的部署。二、 效果图三、 实现原理为了实现上述的效果,kubernetes提供了pod的亲和性和反亲和性来保证pod在节点级别,可用区级别的高可用部署;具体的值为topologyKey:failure-domain.beta.kubernetes.io/zone。四、 实现步骤在ACK上创建完集群后,不论从哪个可用区添加节点,都会对该节点打上对应的可用区标签,比如,一个节点是属于北京可用区a的,那么在加入到kubernetes集群后,该节点上会有一个这样的标签:failure-domain.beta.kubernetes.io/zone: cn-beijing-a。在有了上述标签后,对应用进行多可用区部署时,我们就可以使用一下yaml文件来使不同的pod分配到不同的可用区。 Yaml文件示例:apiVersion: apps/v1kind: Deploymentmetadata: name: redis-cachespec: selector: matchLabels: app: store replicas: 3 template: metadata: labels: app: store spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: “failure-domain.beta.kubernetes.io/zone” containers: - name: redis-server image: redis:3.2-alpine上面yaml文件中的podAntiAffinity:部分规定了node的反亲和性,并且由于使用了topologyKey: “failure-domain.beta.kubernetes.io/zone”,如果failure-domain.beta.kubernetes.io/zone这个key有三种value,比如cn-beijing-a,cn-beijing-b,cn-beijing-c;那么pod会被分配在这三个不同的可用区。并且由于使用了preferredDuringSchedulingIgnoredDuringExecution,所以如果pod个数大于可用区个数的话,pod会尽可能的放在不同的可用区,最后会出现多出来的pod会与原有pod在同一个可用区。上面的使用方式还有很多种,包括node级别的,详细请参考:https://kubernetes.io/docs/co…由于云盘不能跨可用区挂载,如果有pod使用了存储卷,该pod需要被调度到与存储卷相同的可用区的机器上。其他存储卷比如NAS,OSS是可以采用上述部署方式的。本文作者:朱延生阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 18, 2019 · 1 min · jiezi

Table Store: 海量结构化数据实时备份实战

数据备份简介在信息技术与数据管理领域,备份是指将文件系统或数据库系统中的数据加以复制,一旦发生灾难或者错误操作时,得以方便而及时地恢复系统的有效数据和正常运作。在实际备份过程中,最好将重要数据制作三个或三个以上的备份,并且放置在不同的场所异地备援,以供日后回存之用。备份有两个不同的目的,其主要的目的是在数据丢失后恢复数据,无论数据是被删除还是被损坏。备份的第二个目的是根据用户定义的数据保留策略从较早的时间恢复数据,通常在备份应用程序中配置需要备份多长时间的数据副本。由于备份系统至少会包含一个被认为值得保存的所有数据的副本,因此对数据存储的要求可能会很高,组织此存储空间和管理备份过程可能是一项复杂的任务。如今,有许多不同类型的数据存储设备可用于进行备份,还可以通过许多不同的方式来安排这些设备以提供地理冗余,数据安全性和可移植性。在将数据发送到其存储位置之前,会选择,提取和操作它们,目前已经有许多不同的技术来优化备份过程,其中包括处理打开的文件(open files)和实时数据源的优化,以及压缩,加密和重复数据删除等。每个备份方案都应包括演习过程,以验证正在备份的数据的可靠性,更重要的是要认识到任何备份方案中涉及的限制和人为因素。Table Store备份需求分析对于存储系统而言,数据的安全可靠永远是第一位的,要保障数据尽可能高的可靠性,需要从两个方面保障:存储系统本身的数据可靠性:表格存储(Table Store)是阿里云自研的面向海量结构化数据存储的Serverless NoSQL多模型数据库,提供了99.9999999%的数据可靠性保证,在业界属于非常非常高的标准了。误操作后能恢复数据:误操作永远都无法避免,要做的是当误操作发生的时候能尽快恢复,那么就需要有备份数据存在。对于备份,有两种方案,一个是部署同城或异地灾备,这种代价高费用高,更多的用于社会基础信息或金融信息。另一种是将数据备份到另一个价格更低廉的系统,当万一出现误操作的时候,可以有办法恢复就行。一般可以选择文件存储系统,比如阿里云OSS。Table Store备份恢复方案简介下图为Table Store备份恢复的逻辑结构图,基于全增量一体的通道服务我们可以很容易的构建一整套的数据备份和数据恢复方案,同时具备了实时增量备份能力和秒级别的恢复能力。只要提前配置好备份和恢复的计划,整个备份恢复系统可以做到完全的自动化进行。Table Store备份恢复方案实战目前表格存储虽然未推出官方的备份和恢复功能,但是笔者会step-by-step的带大家基于表格存储的通道服务设计属于自己的专属备份恢复方案,实战步骤会分为备份和恢复两部分。1. 备份预准备阶段:需要确定待备份的数据源和备份的目的源,在此次的实战中,分别对应着TableStore的表和OSS的Bucket。确定备份计划和策略使用通道服务SDK编写代码执行备份策略并监测备份过程2. 恢复执行文件恢复确定备份计划和策略备份策略需要确定备份内容、备份时间和备份方式,目前常见的备份策略主要有以下几类。全量备份(Full Backup): 把硬盘或数据库内的所有文件、文件夹或数据进行一次性的复制。增量备份(Incremental Backup): 对上一次的全量备份或增量备份后更新的数据进行的备份。差异备份(Differential Backup): 提供运行全量备份后变更文件的备份。选择式备份:对系统数据的一部分进行的备份。冷备份:系统处于停机或维护状态下的备份。这种情况下,备份的数据与系统该时段的数据应该完全一致。热备份:系统处于正常运转状态下的备份。这种情况下,由于系统中的数据可能随时在更新,备份的数据相对于系统的真实数据可能会有一定的滞后。在此次的实战中,笔者对于备份计划和策略的选择如下(这里可以根据自己的需求进行自定义设计,然后利用通道服务的SDK来完成相应的需求)。备份内容:TableStore 数据表备份时间:全量备份定期执行(时间可调,默认为一周)。增量备份根据配置定期执行,表格存储的通道服务可以保障数据的严格有序性,每个增量文件是流式append的,可随时被消费。备份方式:全量备份+增量备份,热备份。使用通道服务SDK编写代码这部分会结合代码片段的形式讲解,详细的代码后续会开源出去(链接会更新在本文中),尽请期待。在进行实战之前,推荐先阅读通道服务Java SDK的 使用文档。创建一个全量+增量类型的Tunnel,这里可以使用SDK或者官网控制台进行创建。 private static void createTunnel(TunnelClient client, String tunnelName) { CreateTunnelRequest request = new CreateTunnelRequest(TableName, tunnelName, TunnelType.BaseAndStream); CreateTunnelResponse resp = client.createTunnel(request); System.out.println(“RequestId: " + resp.getRequestId()); System.out.println(“TunnelId: " + resp.getTunnelId());}了解通道服务自动化数据处理框架 在通道服务的快速开始里,我们可以看到用户只需要传入处理数据的process函数和shutdown函数即可完成自动化的数据处理。在process函数的入参中会带有List,而StreamRecord包装的正是TableStore里每一行的数据,包括Record的类型,主键列,属性列,用户写入Record的时间戳等。设计TableStore每一行数据的持久化格式 本次实战中我们使用CSV文件格式,当然你也可以用pb或者其它格式,CSV的优点是可读性比较强,每一行数据会对应CSV文件的一行,持久化的格式如下图所示,CSV文件会有四列, TimeStamp列是数据写入TableStore的时间戳(全量时都为0,增量备份为具体的时间戳),RecordType是数据行的操作类型(PUT, UPDATE和DELETE),PrimaryKey为主键列的JSON字符串表示,RecordColumns为属性列的JSON字符串表示。转换部分的核心代码参见如下代码片段,笔者处理这部分用的是univocity-parsers(CSV)和Gson库,有几个地方需要特别注意下:1). Gson反序列化Long类型会转为Number类型,可能会造成进度丢失,有若干解决办法,笔者采用的是将其转为String类型序列化。2). 对于binary类型的数据的特殊处理,笔者进行了base64的编解码。3). 可以直接流式写入OSS中,减少本地持久化的消耗。this.gson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64TypeAdapter()) .setLongSerializationPolicy(LongSerializationPolicy.STRING).create();// ByteArrayOutputStream到ByteArrayInputStream会有一次array.copy, 可考虑用管道或者NIO channel.public void streamRecordsToOSS(List<StreamRecord> records, String bucketName, String filename, boolean isNewFile) { if (records.size() == 0) { LOG.info(“No stream records, skip it!”); return; } try { CsvWriterSettings settings = new CsvWriterSettings(); ByteArrayOutputStream out = new ByteArrayOutputStream(); CsvWriter writer = new CsvWriter(out, settings); if (isNewFile) { LOG.info(“Write csv header, filename {}”, filename); List<String> headers = Arrays.asList(RECORD_TIMESTAMP, RECORD_TYPE, PRIMARY_KEY, RECORD_COLUMNS); writer.writeHeaders(headers); System.out.println(writer.getRecordCount()); } List<String[]> totalRows = new ArrayList<String[]>(); LOG.info(“Write stream records, num: {}”, records.size()); for (StreamRecord record : records) { String timestamp = String.valueOf(record.getSequenceInfo().getTimestamp()); String recordType = record.getRecordType().name(); String primaryKey = gson.toJson( TunnelPrimaryKeyColumn.genColumns(record.getPrimaryKey().getPrimaryKeyColumns())); String columns = gson.toJson(TunnelRecordColumn.genColumns(record.getColumns())); totalRows.add(new String[] {timestamp, recordType, primaryKey, columns}); } writer.writeStringRowsAndClose(totalRows); // write to oss file ossClient.putObject(bucketName, filename, new ByteArrayInputStream(out.toByteArray())); } catch (Exception e) { e.printStackTrace(); }}执行备份策略并监测备份过程运行通道服务的自动化数据框架,挂载上一步中设计的备份策略代码。public class TunnelBackup { private final ConfigHelper config; private final SyncClient syncClient; private final CsvHelper csvHelper; private final OSSClient ossClient; public TunnelBackup(ConfigHelper config) { this.config = config; syncClient = new SyncClient(config.getEndpoint(), config.getAccessId(), config.getAccessKey(), config.getInstanceName()); ossClient = new OSSClient(config.getOssEndpoint(), config.getAccessId(), config.getAccessKey()); csvHelper = new CsvHelper(syncClient, ossClient); } public void working() { TunnelClient client = new TunnelClient(config.getEndpoint(), config.getAccessId(), config.getAccessKey(), config.getInstanceName()); OtsReaderConfig readerConfig = new OtsReaderConfig(); TunnelWorkerConfig workerConfig = new TunnelWorkerConfig( new OtsReaderProcessor(csvHelper, config.getOssBucket(), readerConfig)); TunnelWorker worker = new TunnelWorker(config.getTunnelId(), client, workerConfig); try { worker.connectAndWorking(); } catch (Exception e) { e.printStackTrace(); worker.shutdown(); client.shutdown(); } } public static void main(String[] args) { TunnelBackup tunnelBackup = new TunnelBackup(new ConfigHelper()); tunnelBackup.working(); }}监测备份过程备份过程的监控可以通过表格存储控制台或者 DescribeTunnel 接口完成,DescribeTunnel接口可以实时获取当前Tunnel下每一个Channel的Client(可以自定义), 消费总行数和消费位点等信息。比如用户有下午2点-3点的数据需要同步,若DescribeTunnel获取到的消费位点为下午2点半,则表示备份到一半了,若获取到的消费位点为下午3点,则代表2点-3点的数据已经备份完毕了。执行文件恢复在数据备份完成后,我们可以根据需求进行全量的恢复和部分数据的恢复,来降低RTO。在恢复数据时,可以有一些措施来优化恢复的性能:从OSS下载时,可以使用流式下载或者分片下载的方式,必要时可以增加并发。写入TableStore时,可以使用并发BatchWrite的方式。下图为Restore的实例代码(略去若干细节),首先根据需求算出需要下载的文件名(和备份策略对应),然后用OSS的流式下载读取相应的文件,最后用并发的BatchWrite方式写入TableStore的恢复表中。public class TunnelRestore { private ConfigHelper config; private final SyncClient syncClient; private final CsvHelper csvHelper; private final OSSClient ossClient; public TunnelRestore(ConfigHelper config) { this.config = config; syncClient = new SyncClient(config.getEndpoint(), config.getAccessId(), config.getAccessKey(), config.getInstanceName()); ossClient = new OSSClient(config.getOssEndpoint(), config.getAccessId(), config.getAccessKey()); csvHelper = new CsvHelper(syncClient, ossClient); } public void restore(String filename, String tableName) { csvHelper.parseStreamRecordsFromCSV(filename, tableName); } public static void main(String[] args) { TunnelRestore restore = new TunnelRestore(new ConfigHelper()); restore.restore(“FullData-1551767131130.csv”, “testRestore”); }}总结本文首先介绍了Table Store备份的需求,接着介绍了使用表格存储的通道服务进行数据备份和恢复的原理,最后结合实际的代码片段讲述了如何一步步的构建Tabel Store数据备份恢复方案。参考链接4 Steps to Create Your Backup Planhttps://en.wikipedia.org/wiki/Backup本文作者:琸然阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 7, 2019 · 2 min · jiezi

mysql innodb索引原理

聚集索引(clustered index)innodb存储引擎表是索引组织表,表中数据按照主键顺序存放。其聚集索引就是按照每张表的主键顺序构造一颗B+树,其叶子结点中存放的就是整张表的行记录数据,这些叶子节点成为数据页。聚集索引的存储并不是物理上连续的,而是逻辑上连续的,叶子结点间按照主键顺序排序,通过双向链表连接。多数情况下,查询优化器倾向于采用聚集索引,因为聚集索引能在叶子结点直接找到数据,并且因为定义了数据的逻辑顺序,能特别快的访问针对范围值的查询。聚集索引的这个特性决定了索引组织表中的数据也是索引的一部分。由于表里的数据只能按照一颗B+树排序,因此一张表只能有一个聚簇索引。在Innodb中,聚簇索引默认就是主键索引。如果没有主键,则按照下列规则来建聚簇索引:没有主键时,会用一个非空并且唯一的索引列做为主键,成为此表的聚簇索引;如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。由于主键使用了聚簇索引,如果主键是自增id,那么对应的数据也会相邻地存放在磁盘上,写入性能较高。如果是uuid等字符串形式,频繁的插入会使innodb频繁地移动磁盘块,写入性能就比较低了。B+树(多路平衡查找树)我们知道了innodb引擎索引使用了B+树结构,那么为什么不是其他类型树结构,例如二叉树呢?计算机在存储数据的时候,有最小存储单元,这就好比人民币流通最小单位是分一样。文件系统的最小单元是块,一个块的大小是4k(这个值根据系统不同并且可设置),InnoDB存储引擎也有自己的最小储存单元—页(Page),一个页的大小是16K(这个值也是可设置的)。文件系统中一个文件大小只有1个字节,但不得不占磁盘上4KB的空间。同理,innodb的所有数据文件的大小始终都是16384(16k)的整数倍。所以在MySQL中,存放索引的一个块节点占16k,mysql每次IO操作会利用系统的预读能力一次加载16K。这样,如果这一个节点只放1个索引值是非常浪费的,因为一次IO只能获取一个索引值,所以不能使用二叉树。B+树是多路查找树,一个节点能放n个值,n = 16K / 每个索引值的大小。例如索引字段大小1Kb,这时候每个节点能放的索引值理论上是16个,这种情况下,二叉树一次IO只能加载一个索引值,而B+树则能加载16个。B+树的路数为n+1,n是每个节点存在的值数量,例如每个节点存放16个值,那么这棵树就是17路。从这里也能看出,B+树节点可存储多个值,所以B+树索引并不能找到一个给定键值的具体行。B+树只能找到存放数据行的具体页,然后把页读入到内存中,再在内存中查找指定的数据。附:B树和B+树的区别在于,B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。辅助索引也称为非聚集索引,其叶子节点不包含行记录的全部数据,叶子结点除了包含键值以外,每个叶子结点中的索引行还包含一个书签,该书签就是相应行的聚集索引键。如下图可以表示辅助索引和聚集索引的关系(图片源自网络,看大概意思即可):当通过辅助索引来寻找数据时,innodb存储引擎会通过辅助索引叶子节点获得只想主键索引的主键,既然后再通过主键索引找到完整的行记录。例如在一棵高度为3的辅助索引树中查找数据,那需要对这颗辅助索引树进行3次IO找到指定主键,如果聚集索引树的高度同样为3,那么还需要对聚集索引树进行3次查找,最终找到一个完整的行数据所在的页,因此一共需要6次IO访问来得到最终的数据页。创建的索引,如联合索引、唯一索引等,都属于非聚簇索引。联合索引联合索引是指对表上的多个列进行索引。联合索引也是一颗B+树,不同的是联合索引的键值数量不是1,而是大于等于2。例如有user表,字段为id,age,name,现发现如下两条sql使用频率最多:Select * from user where age = ? ;Select * from user where age = ? and name = ?;这时候不需要为age和name单独建两个索引,只需要建如下一个联合索引即可:create index idx_age_name on user(age, name)联合索引的另一个好处已经对第二个键值进行了排序处理,有时候可以避免多一次的排序操作。覆盖索引覆盖索引,即从辅助索引中就可以得到查询所需要的所有字段值,而不需要查询聚集索引中的记录。覆盖索引的好处是辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。例如上面有联合索引(age,name),如果如下:select age,name from user where age=?就能使用覆盖索引了。覆盖索引的另一个好处是对于统计问题,例如:select count(*) from userinnodb存储引擎并不会选择通过查询聚集索引来进行统计。由于user表上还有辅助索引,而辅助索引远小于聚集索引,选择辅助索引可以减少IO操作。注意事项索引只建合适的,不建多余的因为每当增删数据时,B+树都要进行调整,如果建立多个索引,多个B+树都要进行调整,而树越多、结构越庞大,这个调整越是耗时耗资源。如果减少了这些不必要的索引,磁盘的使用率可能会大大降低。索引列的数据长度能少则少。索引数据长度越小,每个块中存储的索引数量越多,一次IO获取的值更多。匹配列前缀可用到索引 like 9999%,like %9999%、like %9999用不到索引;Where 条件中in和or可以使用索引, not in 和 <>操作无法使用索引;如果是not in或<>,面对B+树,引擎根本不知道应该从哪个节点入手。匹配范围值,order by 也可用到索引;多用指定列查询,只返回自己想到的数据列,少用select ;不需要查询无用字段,并且不使用可能还会命中覆盖索引哦;联合索引中如果不是按照索引最左列开始查找,无法使用索引;最左匹配原则;联合索引中精确匹配最左前列并范围匹配另外一列可以用到索引;联合索引中如果查询中有某个列的范围查询,则其右边的所有列都无法使用索本文作者:信~仰阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 4, 2019 · 1 min · jiezi

Spring Cloud Alibaba迁移指南(三):极简的 Config

自 Spring Cloud 官方宣布 Spring Cloud Netflix 进入维护状态后,我们开始制作《Spring Cloud Alibaba迁移指南》系列文章,向开发者提供更多的技术选型方案,并降低迁移过程中的技术难度。第一篇:一行代码从 Hystrix 迁移到 Sentinel第二篇:零代码替换 Eureka第三篇,我们一起来看看 Spring Cloud Alibaba 是如何使用极简的方式来做到分布式应用的外部化配置,使得应用在运行时动态更新某些配置成为可能。 目前关于 Spring Cloud Config 的标准实现开源方面有三个,分别是:Spring Cloud Alibaba Nacos ConfigSpring Cloud Consul ConfigSpring Cloud Config (Spring Cloud 官方集成的方式)那面对于这么多的实现,Spring Cloud Alibaba Nacos Config 的实现它具有哪些优势呢?大致从以下几个方面来全方位的分析。 Spring Cloud Alibaba Nacos ConfigSpring Cloud Consul ConfigSpring Cloud Config (Spring Cloud 官方集成的方式)配置存储直接依赖于 Nacos。直接依赖于 Consul。通常的组合是Config-server 和 git。配置刷新无需人工干预,自动秒级刷新。无需人工干预,自动秒级刷新。需要人工干预,手动触发/bus/refresh 接口,才能达到配置动态刷新的效果。是否集成第三方服务不需要。不需要。存储需要依赖于git,刷新依赖于 RabbitMQ 。运维组件只需要运维 Nacos 本身即可。只需要运维 Consul本身。通常是要运维 Config-erver,MQ 的服务,提供存储能力的 Git。比较重的第三方依赖无,直接引入starter 即可 。无,直接引入 starter 即可。不仅需要引入 starter,而且还需要引入配置刷新依赖的 spring-cloud-starter-bus-amqp 。推送状态支持无无更新历史查询支持无无配置回滚支持无无配置加解密支持待确认待确认多重容灾支持无无同时 Spring Cloud Alibaba 还可以基于 Spring Cloud Alibaba Nacos Config 无缝对接云上的 ACM,这给一些需要上云的用户带来了极其的方便。综上全方位的对比,Spring Cloud Alibaba Nacos Config 无疑提供了性价比最高的 Spring Cloud Config 的开源实现。下面以一个快速上手的案例体验一下 Spring Cloud Alibaba Nacos Config 的实现是如何使用的。同时也提供了简单的方式给那些想转用 Spring Cloud Alibaba Nacos Config 的同学做一些参考。第 1 步:Nacos 服务端初始化。1.1 启动 Nacos Server。启动方式可见 Nacos 官网 。1.2 添加配置。启动好 Nacos 之后,在 Nacos 控制台添加如下的配置。Data ID: ${spring.application.name}.propertiesGroup : DEFAULT_GROUP配置格式: Properties配置内容: ${key}=${value}注意:Data Id 是以 properties(默认的文件扩展名方式)为扩展名。文件名以 &dollar;{spring.application.name} 配置参数为主。配置内容:当你想从其他的存储源(例如: git) 要往 Nacos 进行迁移的话,目前只能通过手动的方式进行逐个的添加。&dollar;{key} 是根据您的业务场景需要配置的或者迁移的 key, &dollar;{value} 就是对应的具体值。第 2 步:Spring Cloud Alibaba Nacos Config 客户端使用方式。2.1 添加 maven 依赖。为了能够在应用程序中使用 Nacos 来实现应用的外部化配置,在构建应用的同时或者已经存在的应用需要引入一个 Starter,如下所示:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>0.2.2.BUILD-SNAPSHOT</version></dependency>2.2 添加相关配置。客户端需要和 Nacos 服务端进行通信,因此需要配置 Nacos 服务端的地址。在您的应用配置文件中新增如下配置,这里以 application.properties 为例。spring.cloud.nacos.config.server-addr=127.0.0.1:8848完成以上两个步骤,就已经完成了 Spring Cloud Alibaba Nacos Config 的基本使用。完整的使用可参考 Spring Cloud Alibaba 的管方 Wiki 文档。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 28, 2019 · 1 min · jiezi

mysql中生成时间维度的存储过程(存储过程示例)

本文主要记录在BI和数据分析过程中碰到的生成时间维度的问题,另外也是一个mysql的存储过程基础示例包含:存储过程基本语法、变量定义、while循环、异常处理以下存储过程生成了以当前日期为基准前后3650天的日期记录sql如下:创建表:CREATE TABLE dim_date ( id int(8) NOT NULL DEFAULT ‘0’, key date NOT NULL DEFAULT ‘0000-00-00’, year int(4) NOT NULL, quarter int(1) NOT NULL, month int(2) NOT NULL, week int(1) NOT NULL COMMENT ‘星期’, weekofyear int(2) NOT NULL COMMENT ‘一年中的第几周’, day int(2) NOT NULL COMMENT ‘日’, dayofyear int(3) NOT NULL COMMENT ‘一年总的第几天’, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;存储过程:delimiter //DROP PROCEDURE IF EXISTS getAllDate; CREATE PROCEDURE getAllDate()BEGIN DECLARE count int default 0; DECLARE startDay DATE DEFAULT date(now()); DECLARE endDay DATE DEFAULT DATE(NOW()); – 定义异常处理方式 http://www.cnblogs.com/cookiehu/p/4994278.html DECLARE out_status VARCHAR(200) DEFAULT ‘OK’; DECLARE CONTINUE HANDLER FOR 1062 SET out_status=‘Duplicate Entry’; – 异常处理方式完毕 WHILE count<3650 DO INSERT INTO dim_date(id, key, year, quarter, month, week, weekofyear, day, dayofyear) VALUES (cast(DATE_FORMAT(startDay,’%Y%m%d’) as UNSIGNED), startDay, YEAR(startDay), QUARTER(startDay), MONTH(startDay), WEEKDAY(startDay)+1, week(startDay,1), DAY(startDay), DAYOFYEAR(startDay)); set count = count +1; set startDay = DATE_ADD(DATE(now()),INTERVAL count DAY); SET endDay = DATE_SUB(DATE(NOW()),INTERVAL count DAY); INSERT INTO dim_date(id, key, year, quarter, month, week, weekofyear, day, dayofyear) VALUES (cast(DATE_FORMAT(endDay,’%Y%m%d’) as UNSIGNED), endDay, YEAR(endDay), QUARTER(endDay), MONTH(endDay), WEEKDAY(endDay)+1, week(endDay,1), DAY(endDay), DAYOFYEAR(endDay)); END WHILE;END//delimiter ;调用存储过程– TRUNCATE table dim_date;call getAllDate(); ...

February 28, 2019 · 1 min · jiezi

mysql-存储过程

1、什么是存储过程为以后的使用而保存的一条或多条MySQL语句的集合。 存储过程思想上就是数据库 SQL 语言层面的代码封装与重用。2、为什么要使用存储过程把处理封装在容易使用的单元中,简化复杂的操作防止错误保证了数据的一致性简化对变动的管理。(修改对应表名、列名等修改对应存储过程的代码,对于使用的人不需要知道变化)提高性能灵活总的来说是简单、安全、高性能缺点:编写比SQL语句复杂权限问题(可能无权、一般都是使用存储过程、没有创建存储过程的权限)3、创建存储过程CREATE PROCEDURE productpricing()BEGINSELECT Avg(prod_price) AS priceaverageFROM products;END注意:在命令行中输入的问题mysql> delimiter //mysql> CREATE PROCEDURE productpricing() -> BEGIN -> SELECT Avg(prod_price) AS priceaverage -> FROM products; -> END //4、使用存储过程存储过程实际上是一种函数CALL productpricing();4、删除存储过程 drop procedure productpricing; drop procedure if EXISTS productpricing;5、使用参数一般,存储过程并不显示结果,而是把结果返回给你指定的变量 变量(variable)内存中一个特定的位置,用来临时存储数据。CREATE PROCEDURE productpricing( OUT p1 DECIMAL(8,2), OUT ph DECIMAL(8,2), OUT pa DECIMAL(8,2))BEGINSELECT MIN(prod_price)INTO p1FROM products;SELECT MAX(prod_price)INTO phFROM products;SELECT avg(prod_price)INTO paFROM products;END;关键字OUT指出相应的参数用来从存储过程传出 一个值(返回给调用者)。MySQL支持IN(传递给存储过程)、OUT(从存 储过程传出,如这里所用)INOUT(对存储过程传入和传出)类型的参 数。变量名 所有MySQL变量都必须以@开始。调用存储过程call productpricing(@pricelow,@pricehign,@priceaverage);查询SELECT @priceaverage;SELECT @priceaverage,@pricehign,@pricelow;使用in和out创建CREATE PROCEDURE ordertotal( IN onumber INT, OUT ototal DECIMAL(8,2))BEGINSELECT sum(item_pricequantity)FROM orderitemsWHERE order_num = onumberINTO ototal;END;调用call ordertotal(20005,@total);查询select @total;6、建立智能存储过程迄今为止使用的所有存储过程基本上都是封装 MySQL简单的SELECT语句。虽然它们全都是有效的存储过程例子,但它们所能完成的工作你直接用这些被封装的语句就能完成(如果说它们还能带来更多的东西。那就是使事情更复杂)。只有在存储过程内包含业务规则和智能处理时,它们的威力才真正显现出来。 考虑这个场景。你需要获得与以前一样的订单合计,但需要对合计增加营业税,不过只针对某些顾客(或许是你所在州中那些顾客)。那么,你需要做下面几件事情: 1、获得合计(和以前一样) 2、把营业税有条件的添加到合计 3、返回合计(带或不带税的)我们输入如下代码:– Name: ordertotal // 添加注释– Parameters: onumber = order number– taxable = 0 if not taxable, 1 if taxtable– ototal = order total variableCREATE PROCEDURE ordertotal (IN onumber INT,IN taxable BOOLEAN,OUT ototal DECIMAL(8,2)) COMMENT ‘Obtain order total, optionally adding tax’BEGIN – Declare variable for total DECLARE total DECIMAL(8,2); // 声明变量 – Declare tax percentage DECLARE taxrate INT DEFAULT 6; – Get the order total SELECT Sum(item_pricequantity) FROM orderitems WHERE order_num = onumber INTO total; – Is this taxable? IF taxable THEN – yes,so add taxrate to the total SELECT total+(total/100*taxrate) INTO total; END IF; – And finally, save to out variable SELECT total INTO ototal;END;此存储过程有很大的变动。首先,增加了注释(前面放置 –)。在存储过程复杂性增加时,这样做特别重要。 添加了另外一个参数 taxable,它是一个布尔值(如果要增加税则为真,否则为假)。 在存储过程体中,用 DECLARE语句定义了两个局部变量。 DECLARE要求指定变量名和数据类型,它也支持可选的默认值(这个例子中的 taxrate的默认被设置为 6%)。SELECT 语句变,因此其结果存储到 total(局部变量)而不是 ototal。 IF 语句检查taxable是否为真,如果为真,则用另一SELECT语句增加营业税到局部变量 total。最后,用另一SELECT语句将total(它增加或许不增加营业税)保存到 ototal。 注意:COMMENT关键字 ,本例子中的存储过程在 CREATE PROCEDURE语句中包含了一个 COMMENT值。 它不是必需的,但如果给出,将在SHOW PROCEDURE STATUS的结果中显示。这显然是一个更高级,功能更强的存储过程。为试验它,请用以下两条语句: 第一条:call ordertotal(20005, 0, @total);SELECT @total;输出:+——–+| @total |+——–+| 38.47 |+——–+第二条:call ordertotal(20009, 1,@total);SELECT @total;输出:+——–+| @total |+——–+| 36.21 |+——–+BOOLEAN值指定为1 表示真,指定为 0表示假(实际上,非零值都考虑为真,只有 0被视为假)。通过给中间的参数指定 0或1 ,可以有条件地将营业税加到订单合计上。这个例子给出了 MySQL的IF 语句的基本用法。 IF语句还支持 ELSEIF和ELSE 子句(前者还使用 THEN子句,后者不使用)。在以后章节中我们将会看到 IF的其他用法(以及其他流控制语句)。7、检查存储过程为显示用来创建一个存储过程的CREATE语句show create PROCEDURE ordertotal;为了获得包括何时、由谁创建等详细信息的存储过程列表show procedure status;表比较多,用like过滤show procedure status like ‘ordertotal’; ...

February 24, 2019 · 2 min · jiezi

优化体系结构 - 算法外置优化计算结构

【摘要】无论存储过程还是 JAVA 程序实现的数据计算层,都会存在很多不足和不方便!若采用专业的数据计算引擎,又会带来怎样的好处呢?去乾学院看个究竟吧!优化体系结构 - 算法外置优化计算结构【下载附件】优化体系结构 - 算法外置优化计算结构

February 18, 2019 · 1 min · jiezi

Euler 今日问世!国内首个工业级的图深度学习开源框架,阿里妈妈造

阿里妹导读:千呼万唤始出来!阿里妈妈正式公布重磅开源项目——图深度学习框架Euler。这是国内首个在核心业务大规模应用后开源的图深度学习框架。此次开源,Euler内置了大量的算法供用户直接使用,相关代码已经可在GitHub上进行下载。图学习和深度学习都是人工智能的一个分支,作为阿里巴巴旗下的大数据营销平台,阿里妈妈创新性地将图学习与深度学习进行结合,推出了Euler,可帮助大幅度提升营销效率。Euler已在阿里妈妈核心业务场景进行了锤炼和验证,同时,在金融、电信、医疗等涉及到复杂网络分析的场景中也具有很高的应用价值。例如,用户可以利用Euler对基于用户交易等金融数据构建的复杂异构图进行学习与推理,进而应用于金融反欺诈等场景。下面让我们一起走进Euler的世界。Euler 开源地址 : https://github.com/alibaba/euler1. 概述过去几年随着数据规模和硬件计算力的迅速增长,深度学习技术在工业界被广泛应用并产生了巨大的技术红利。当前应用已经相对成熟,下一步的技术红利在哪里还在积极探索之中。图神经网络将端到端学习与归纳推理相结合,有望解决深度学习无法处理的关系推理、可解释性等一系列问题。对结构知识的表达、计算和组合泛化是实现具备human-like AI的关键,图神经网络有希望在这些方面形成突破,使得机器能力进一步提升,因此对图神经网络的深入应用有希望形成下一波技术红利。图作为表达能力很强的通用的数据结构,可以用来刻画现实世界中的很多问题,例如社交场景的用户网络、电商场景的用户和商品网络、电信场景的通信网络、金融场景的交易网络和医疗场景的药物分子网络等等。相比文本、语音和图像领域的数据比较容易处理成欧式空间的Grid-like类型,适合现有的深度学习模型处理,图是一种非欧空间下的数据,并不能直接应用现有方法,需要专门设计的图神经网络系统。1.1Euler的核心能力1)大规模图的分布式学习工业界的图往往具有数十亿节点和数百亿边,有些场景甚至可以到数百亿节点和数千亿边,在这样规模的图上单机训练是不可行的。Euler支持图分割和高效稳定的分布式训练,可以轻松支撑数十亿点、数百亿边的计算规模。2)支持复杂异构图的表征工业界的图关系大都错综复杂,体现在节点异构、边关系异构,另外节点和边上可能有非常丰富的属性,这使得一些常见的图神经网络很难学到有效的表达。Euler在图结构存储和图计算的抽象上均良好的支持异构点、异构边类型的操作,并支持丰富的异构属性,可以很容易的在图学习算法中进行异构图的表征学习。3)图学习与深度学习的结合工业界有很多经典场景,例如搜索/推荐/广告场景,传统的深度学习方法有不错效果,如何把图学习和传统方法结合起来,进一步提升模型能力是很值得探索的。Euler支持基于深度学习样本的mini-batch训练,把图表征直接输入到深度学习网络中联合训练。4)分层抽象与灵活扩展Euler系统抽象为图引擎层、图操作算子层、算法实现层三个层次,可以快速地在高层扩展一个图学习算法。实际上,Euler也内置了大量的算法实现供大家直接使用。1.2 Euler内置的算法实现考虑到框架的易用性,我们内置了多种知名算法以及几种我们内部的创新算法。所有实现,我们仔细进行了测试,保证了算法运行效率,且算法效果与原论文对齐。用户无需进行开发,注入数据到平台后,可以直接使用。我们内置的算法列表见下表。有关我们内部算法的详细信息请见2.3节。2. 系统设计Euler系统整体可以分为三层:最底层的分布式图引擎,中间层图语义的算子,高层的图表示学习算法。下边我们分开描述各个层次的核心功能。2.1分布式图引擎为了支持我们的业务,我们不仅面临超大规模图存储与计算的挑战,还需要处理由多种不同类型的点,边及其属性构成异构图的复杂性。我们的分布式图引擎针对海量图存储,分布式并行图计算及异构图进行了优化设计,确保了工业场景下的有效应用。首先为了存储超大规模图(数十亿点,数百亿边),Euler必须突破单机的限制,从而采用了分布式的存储架构。在图加载时,整张图在引擎内部被切分为多个子图,每个计算节点被分配1个或几个子图进行加载。为了充分利用各个计算节点的能力,在进行图的操作时,顶层操作被分解为多个对子图的操作由各个节点并行执行。这样随着更多节点的加入,我们可以得到更好的服务能力。其次,我们引入了多replica的支持。从而用户可以灵活平衡shard与replica的数量,取得更佳的服务能力。最后,我们针对图表示学习优化了底层的图存储数据结构与操作算法,单机的图操作性能获得了数倍的提升。多种不同类型的边,点与属性所组成的异构图,对很多复杂的业务场景必不可少。为了支持异构图计算能力,底层存储按照不同的节点与边的类型分别组织。这样我们可以高效支持异构的图操作。2.2中间图操作算子由于图学习算法的多样性以及业务的复杂性,固定的某几种甚至几十种算法实现无法满足客户的所有需求。所以在Euler设计中,我们围绕底层系统的核心能力着重设计了灵活强大的图操作算子,且所有算子均支持异构图操作语义。用户可以利用它来快速搭建自己的算法变体,满足独特的业务需求。首先,Euler分布式图引擎提供了C++的API来提供所有图操作。基于这个API,我们可以方便的基于某个深度学习框架添加图操作的算子,从而利用Euler C++接口访问底层图引擎的能力。我们支持广泛使用的深度学习框架,比如阿里巴巴的X-DeepLearning与流行的TensorFlow。后继我们也会考虑支持其它的深度学习框架,比如PyTorch。利用灵活的图操作算子,机器学习框架可以在每个mini-batch与Euler交互,动态扩充与组织训练样本。这样,Euler不仅支持传统的以图为中心的学习模式,且可以把图学习的能力注入传统的学习任务,实现端到端训练。按照功能分类,我们的核心系统提供的API可以分类如下:全局带权采样点和边的能力。主要用于mini-batch样本的随机生成以及Negative Sampling。基于给定节点的邻居操作。这个是图计算的核心能力包括邻居带权采样,取Top权重的邻居等。点/边的属性查找。这个能力使得算法可以使用更丰富的特征,而不仅限于点/边的ID特征。2.3高层算法实现如1.2节所述,除了LINE算法以外,我们实现的算法可以分为随机游走与邻居汇聚两大类算法。有关外部算法的详细信息,请参见1.2节提供的论文链接。下面我们详细介绍内部的三个创新算法,相关论文的链接我们会在github上给出。Scalable-GCN它是一种高效的GCN训练算法。GCN以及更一般的Graph Neural Network (GNN)类的方法由于能有效的提取图结构信息,在许多任务上均取得了超过以往方法的效果。但是GCN的模型会引入巨大的计算量,导致模型的训练时间不可接受。Scalable-GCN在保证优秀效果的前提下,把mini-batch GCN的计算复杂度从层数的指数函数压到线性。这使得在阿里妈妈的海量数据下应用三层GCN成为可能,广告匹配的效果获得了显著提升。LsHNELsHNE是我们结合阿里妈妈搜索广告场景创新地提出一种无监督的大规模异构网络embedding学习方法。区别于DeepWalk类算法,LsHNE的特点包括:a) 采用深度神经网络学习表达,可以有效融合Attribute信息;b)考虑embedding表示的距离敏感需求,提出两个负采样原则:分布一致性原则和弱相关性原则;c)支持异构网络。LasGNNLasGNN是一种半监督的大规模异构图卷积神经网络学习方法, 它有效融合了图结构知识信息和海量用户行为信息,大幅提升了模型精度,是工业界广告场景下首次应用半监督图方法。该方法有多处创新,例如将metapath的思想应用于图卷积网络中,并提出了metapathGCN模型,有效解决了异构网络的卷积问题;提出了metapathSAGE模型,在模型中我们设计高效的邻居采样的方法,使得大规模的多层邻居卷积成为可能。3. 应用实例Euler平台已经在阿里妈妈搜索广告的多个场景下广泛实用,并取得了出色的业务效果,例如检索匹配场景、CTR预估场景、营销工具场景和反作弊场景等。我们以匹配场景的为例来看下Euler的应用。广告匹配的任务是给定用户搜索请求,匹配模块通过理解用户意图,快速准确地从海量广告中找到高质量的小规模候选广告集,输送给下游的排序模块进行排序。我们首先使用一些传统的挖掘算法,从用户行为日志、内容属性等维度挖掘出Query(查询词), Item(商品)和Ad(广告)的多种关系,然后利用Euler平台的LsHNE方法学习图中节点的embedding,这里节点embedding后的空间距离刻画了原来图中的关系,对于在线过来的请求通过计算用户查询词向量、前置行为中节点向量和广告节点向量之间的距离进行高效的向量化最近邻检索,可以快速匹配到符合用户意图的广告。图2展示了LsHNE方法的离线和在线流程。具体图3展示了样本构造和网络结构示意。本文作者:让你久等了阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

January 21, 2019 · 1 min · jiezi

与“十“俱进 阿里数据库运维10年演进之路

导语阿里巴巴集团拥有超大的数据库实例规模,在快速发展的过程中我们在运维管理方面也在不断的面临变化,从物理器到容器、从独占到混布、从本地盘到存储计算分离、从集团内到大促云资源,从开源的MySQL到自研分布式数据库,运维管控进行了自我革新与进化。作者—谭宇(花名:茂七),阿里巴巴高级技术专家。2009年加入阿里,对分布式系统和数据库领域有很大的兴趣。目前负责阿里巴巴集团数据库中台建设,支撑了集团数据库在容器化、存储计算分离、在离线混部、大规模迁移建站以及智能运维等技术探索与落地。本文梳理了阿里巴巴数据库运维发展历程以及对未来数据库自治时代的看法,期待与诸位一起讨论。正文我在阿里快十年了,前五年做一些分布式系统开发相关的工作,参与的系统包括TFS/Tair/OceanBase,后五年聚焦在数据库运维平台及服务的建设,从搭建数据库集群、数据采集等底层运维到外部客户服务、POC支持等都有所经历,好的想法历来稀少,外加个人天资愚钝,不敢说有什么独创的想法,都是实践过程中的一些感悟,且与大家分享,也是对过去一段时间的总结。关于阿里的数据库,大家可能已经听说过很多,阿里巴巴数据库技术的发展与整个集团的技术发展类似,从商业到开源再到自主研发。早在09年以前,阿里巴巴数据库或DBA团队已经在业界非常知名,拥有多名Oracle ACE / ACE Director,外加自发性的与业界的交流、分享以及著作,构建了非常强的影响力,很多人因此吸引而加入,这是一段荣耀时光,当时很多知名人物现在有的在创业、有的仍在集团不同的领域奋斗,江湖中仍然可以搜索到他们的传说。后来就是轰轰烈烈的去IOE运动了,刚入职时经常在内部BBS上看到各种成功去除Oracle的帖子,基本套路就是DBA和业务开发一起配合,通过各种脚本把数据迁移到MySQL上。在这个过程中,遇到过很多问题,也在积极寻求各种新的技术,比如为了突破磁盘性能问题,在当时主流的还是机械硬盘的时候,使用了Fusion-IO等,也在MySQL内核上开始各种改进,形成了AliSQL。关于去IOE、各自数据库内核技术、支撑的业务这些方面,讲的很多,大家可以搜到各自技术相关的文章,但很少有人讲过这背后有一个什么样的平台来支持这些业务变化以及技术迭代。过去的5年里,我和我的团队一直在做数据库运维或者是服务方面的事情,很难,我相信各位如果有做过这方面经验会感同身受。一方面,这是运维类或服务类系统的“原罪”,这类系统形成初期,它只是一个工具或一个平台,使命是支撑好业务,自己并不实际产生价值。所有的技术要在这里落地,等落完地好像和你又没什么关系,价值感比较弱。今天K8S等系统的出现说明这个也可以做得很好,但相对来说这是一个更难做好的领域。另一方面,业务的复杂性、技术栈的多样性以及所依赖的组件决定了这个系统在实现层面很难,你需要把各个组件一层一层的串联起来。从业务访问到数据库内核再到底层的网络、存储、OS、硬件等,任何一个层面出了问题都会集中反应到你的系统中,实现人员面临着从上到下各个层面问题的理解、异常的处理,对团队及个人能力要求极高。一个很具体的例子,我们的运维系统涉及了前端、大数据处理、算法、数据库、底层软硬件等各个技术领域。在最初期团队不可能有各个领域的专家,需要每个同学了解并解决不同的领域的问题。我想就这些方面,系统性地跟大家介绍一下我们所做的一些工作。主要包括三个方面:第一,我们整个系统的发展历程,所谓从历史看未来,不知道过去,无法推断出未来我们的样子。第二,现阶段的技术和产品,比如我们如何支撑我们现有的工作,双11大促等。第三,从过去和现在出发,我们未来一段时间要到达的样子。1. 从历史看未来阿里巴巴数据库运维发展的历程,主要有这几个阶段。09年以前,以商业数据库为主,去IOE也才开始。之前没有整体运维规划、运维平台。使用了各类脚本、工具。在09年以后,由于规模迅速膨胀,这个时候自然产生了一些工具团队,把各类脚本拼在一起,弄个界面,形成了最初的产品。接着,随着复杂度进一步增加,以及云计算的推动。交付方面有了更高的要求,形成了服务化,比如DBaaS等。近年来,随着大数据、机器学习等技术的发展,AIOPS催生智能化。在智能化的基础之上,对各类服务平台的服务质量的进一步要求,也就是自治。总体来讲,有两次比较大的革新。第一次是从产品化到服务化。最初,我们的产品形成非常简单。没有什么平台,没有什么系统,大家一边干活一边沉淀一些脚本,到处分发。随着规模的增长,原来的那套脚本需要管理起来了,我相信很多团队最开始都会设立一个工具组,专门来干这个事情。这就会演变成一个团队做工具,另一个团队来使用,慢慢的两者之间的GAP就出现了。工具团队有工具团队的KPI,业务团队有业务团队的KPI,分歧会逐渐增大。另外一个问题则是大家都在攒工具,攒平台。结果这些平台之间是相互不能通信的。比如一个应用开发,需要数据库、搜索、分布式存储等各个系统,开发人员需要去逐个申请,效率不高。服务化的变革就是在这种情况下发生的。我们不提供工具、平台,而提供服务。这些服务之间相互打通,并且我们对提供的服务有相关SLA保证。这次革新可以说是云计算的基础,云计算的本质是IT资源交付技术的进步,这是云计算带给我们的最大价值。第二次革新是自治,我们目前正处于这次革新中。对SLA或者服务质量的追求是没有止境的。现在很火的Cloud Native、Serverless本质上都是对更高服务质量的一种追求。要提升服务水平,关键点有两个,一是规模,规模大了才能做更多事情,比如混合部署、智能调度、机器学习,都要求一定的规模和大量的数据。这也符合当前提供基础服务的云计算趋于集中的趋势。规模也是问题的根源,管理一千个实例和十万个实例所需的技术完全不一样,所以另一个关键点是技术水平,有了规模还必须有相应的技术,比如容器化、机器学习、存储计算分离、RDMA网络等技术的提升。2. 理想照进现实当然技术的积累是一个长期的过程,积累到一定程度就会引起质变。我们这些年在系统建设、技术积累方面所做了许多工作。先来看一组数据,这是刚刚过去的双十一数据库相关的一些情况。大家可能看过一些数据,比如成交额,交易峰值。对于背后的数据库而言,每秒有超过5000万次的访问。特别是在高峰期,读写比是和平时不一样的。通常一般系统读写比大约是9:1或者7:1。但在双11高峰时,数据库的读写比可能是2:1。在写入比例极高的情况下,要求数据库不能出现任何抖动或者延迟,我们对任何一种新技术的引入都非常严格。另外,阿里巴巴大促场景非常复杂,包括线上线下以及海内外多种场景。基础设施分布在全球多地,数十个机房同时支撑,系统复杂性非常高。总结来看,我们的业务场景大致有以下几个特点:业务多样性。作为数据库中台,数据库团队要支撑集团所有业务。包括核心电商、线下新零售场景以及各个独立子公司。各种场景对数据库的要求也不一样,比如线上场景就要求高并发低延时,故障快速恢复。线下场景则要求绝对可用,而且接入及使用数据库的方式都不受控制。而新加入阿里体系的收购公司,有原来的运维体系,要求他们做改变也不太现实。总之需求的多样性对数据库的要求非常高。基础设施多样化,数据中心分布在全球,有的用公有云、有的有自建机房,有的用物理机,有的用Docker、用弹性计算等,整个集团就是一个超级大的混合云。双11超级大热点,除了成本和性能方面,双11在弹性方面有很高的要求。我们也不可能为双11买这么多机器,那太浪费了。早期,会在不同的业务线之间进行拆借,比如借云的机器或者借离线的机器,大促后归还,全靠人肉搬机器。整个大促周期非常长,人力成本和机器成本都很高。针对以上情况,我们形成了如下架构。主要思路是向下层屏蔽差异,向上层提供多样化服务能力,中间围绕着弹性、稳定性、智能化进行建设。早期的运维系统因为各种原因,没有设计好的架构导致难以扩展,最后越来越臃肿,推翻重构的事情并不少见。现今,我们设计了服务化的运维系统整体架构:一来可以清晰地理顺系统各个模块之间的交互方式并标准化,彻底解决原来工具时代遗留下来的各自为政,各个功能散落在不同地方的问题,整个系统的发展不再背负历史包袱;二来可以解决技术栈太多的问题,从前端到底层采集、算法分析,我们不可能统一成一个框架、一种语言。让这些模块能互不影响、互相交互,是整个系统能做强的基础;三来可以将整个系统的数据集中起来,为后续智能化所需要的统一数据、统一算法提供基本要素;四来可以向外提供统一形式、功能多样化的服务。要想做好做强一个服务类的系统,服务化是第一步。在底层,我们做了统一的资源调度层,用来屏蔽底层计算、存储、网络资源的差异,向上交付标准的容器。中间是数据库层。因为业务的多样性,数据库类型多种多样,运行在不同的环境,我们通过统一的命令通道和采集通道的抽象来屏蔽这些差异。再往上是传统的数据库运维层,包括常见的数据库的生命周期管理,我们称之为Lego,希望OPS这样的基础功能能像乐高一样百变组合,迅速搭建我们想要的功能。还包括数据采集、处理存储的模块Kepler,我们希望把所有的运行数据实时采集到,然后通过大数据处理、机器学习等手段发掘出深层价值,采集的数据包括OS、网络、存储,数据库的SQL流水、性能指标等等,整个处理的数据量非常大,并且所有指标都要求是秒级的。每秒都要处理超过100G的原始报文。再往上是智能决策层,这一层完成自动修复与优化的工作,比如预期内的故障,异常处理。也通过采集到的数据,做一些分析和决策。我们把整个系统的功能以服务的形式提供出来,大家可以在这个基础之上定制想要的功能。过去几年,我们在架构实现方面一直坚持“一个平台、一套架构,集团孵化、云上输出”的策略,集团内部数据库管控平台提供服务,所有模块在一套架构下实现,产品在集团检验后开始在云上输出。不同的时期有不同的坚持,在智能化时代,我们对这个架构及策略也有所调整,这个在后面会提及。解决架构问题后,我们过去两年主要围绕几个能力进行建设,一是容器化与存储计算分离,二是快速弹性与混部的能力,三是规模化交付与智能运维,这几项工作都是今天能够发展成为集团数据库中台以及支撑双十一的关键能力。第一,容器化是技术的量变到质变,容器并没有很多开创性的技术,各种技术合在一起开辟了新的思路。所以在把数据库放到容器里首先要突破我们的运维思路,坚定可以把数据库放到容器里的这个想法。当然这个过程中也遇到过稳定性和性能问题,比如网络在使用bridge模式的时候,会有些CPU的增加。最终在网络团队不断优化后,基本可以做到与物理机持平。容器化一方面解决了很多环境问题,另一方面也为数据库的调度提供了可能,我们从16年开始做数据库容器化,到今年,绝大部份的数据库都跑在了容器里。第二,存储计算分离。其实数据库最开始就是存储计算分离架构的。在互联网时代,这个架构在最初遇到了瓶颈,因为互联网时代的容量扩张非常快。然后出现了分布式系统,把计算搬到数据所在的地方。但是随着技术的发展,特别是云的交付方式,存储计算分离的交付则更为便捷。交付多少计算能力,交付多少存储,一目了然。另外,存储和计算的发展也不太均衡,比如双11的时候,我要求的是计算能力,其实存储并没有增加多少。所以随着技术的发展,我们这一圈基本上又转了回来。当然存储计算分离要不要上,我们也是经过了很长时间的讨论,今天来看,上存储计算分离这个决定是对的。在这个过程中也遇到很多问题,主要是延迟的问题,毕竟经过一层网络,IO时间是有增加的。我们最开始上了左边这个架构,将远程存储挂载到本地,这个延迟要较本地盘大很多,核心业务难以接受,在这个基础之上,我们大规模引入RDMA网络,通过DBFS bypass掉kernel,延时基本能和本地盘相当,所以今年所有的核心业务就跑在了这个架构上。有了容器化和存储计算分离的基础,就可以比较好的解决弹性问题了。之前我们的弹性主要靠搬数据加搬机器,现在数据可以不用搬了。我们大促所用的机器主要来自两个地方,一个是离线资源,另外一个是云资源,我们用完之后云可以继续对外售卖。大家知道,双11的高峰期主要在零点时段。所以我们在高峰期来的时候弹性扩容,高峰期结束立即缩容,还机器给别人用。我们结合集团的调度,做了一套混部调度系统,可以做到数据库快上快下,今年我们的核心集群10分钟就可以完成弹性扩缩,而我们最终的目标是在1分钟内完成。第三,交付和诊断。我们说云计算是IT资源交付能力的进步。我们基本完成了向用户交付数据库资源,开发人员可以通过系统自助完成数据库资源的申请与使用。如果只是把交付理解为用户自助获取数据库资源的话,我们已经完成得很好了。但集团有更严苛和复杂的交付任务。比如下面两个例子:大促时需要在上十万个数据库实例里扩容数千甚至上万个实例,大促完成后还需要缩容回来。每年有固定的或临时的建站、迁站等操作,例如今年的一路向北和上海、张北多次建站,可能会涉及到数万数据库实例及数十PB数据,这些都非常考验我们交付的能力。之前的常规做法是让人来评估,确定好操作的数据库范围,算好需要多少机器资源,如何摆放等,再通过我们提供的迁移操作来完成。人需要来控制其中的每一个步骤,这是一个相当繁琐的工作。每年都要做那么几次,在我们今天要求快上快下的时候就显得特别力不从心。所以我们提出软件定义部署的概念,类似常说的编排。主要做两个事情,一是把我们的这些操作都精确定义和记载下来,线上的运行环境也能用代码精确定义出来。二是把中间的腾挪步骤交给系统,人只需要描述最终的状态,在我们预测准确到一定程度后,这个最终描述状态也可以由系统来完成,真正的完成大促自动化交付。可以看到,我们的链路其实很长,中间的各个组件出了问题诊断是一件很难的事情。Gartner有一个名词叫AIOPS,相信大家都听说过,其实Gartner提出AIOPS很早,最开始指的是基于算法的OPS,随着AI技术的发展呢,他顺势把这个词的写法给改了,但本质上没有变,仍然是依托大数据、算法来改变OPS。应该说这也是个朴素的概念,我们在差不多时刻也提出了这个想法,最开始叫做数据驱动,后来改名为运行数据与数据运营,也是通过各种算法,比如基线、异常检测、关联分析、趋势预测等等来自动决策或辅助我们决策。这便是CloudDBA的初衷,先把各种采集到的数据汇聚统一、预处理再加上领域知识和算法,打通从用户到DB,从DB到底层硬件这两个链路。在双11的时候也能实时的诊断访问链路。当然这里待挖掘的还非常多,现在我们可以说只应用了非常小的一部份。最后,我把之前讲的这些都融进了一个产品HDM,全称是混合云数据库管理平台。Gartner有一份报告指出,到2020年的时候,有85%的企业会使用混合云的架构。这和我们的判断是一致的。之前提到过,阿里巴巴集团就是一个超大的混合云,所以我们推出了HDM,帮助企业把混合云数据库架构打通。HDM主要提供两大功能,一是统一管理,不管是云上的还是云下还是其他云的数据库,都可以进行统一管理与诊断。二是弹性扩展,一键把数据库上云也不再是梦想。在数据库层消除本地IDC和云的区别。在提出HDM后一段时间里,我一度认为这基本上就是数据库服务的未来了。但这些年,不管是数据库领域,还是运维领域,都在飞速的向前发展,我们似乎又到了一个技术集中爆发的时间点。一方面是新的软硬件技术,比如容器、高速网络,机器学习,另外一个是云计算的发展,都在不断的推动我们向前,提供更好的交付及服务。3. 通往智能之路:自治数据库平台在数据库领域,有自治数据库、智能数据库,在运维领域,有AIOPS等等。这对数据库运维来说到底意味着什么,我们结合过去和现在的情况,提出了自治数据库平台。这个定义是很多人一起讨论了很久才定出来的。首先是平台的能力和目标,我们希望能做到自动驾驶,简单的说就是不需要人的参与。要做到这个,就要具备自感知、自决策、自恢复、自优化四大能力。其次是平台能为数据库赋能,今天的现状是我们用了很多种数据库,不能对每个数据库有很高的要求才能自治,我们可以进行能力分级。我们也有非常明确的业务目标,这是阿里数据库事业部掌门人公开的目标:在2020财年结束的时候,阿里集团85%的数据库实例要能做到自动驾驶。我为此定了两个评估指标,一是没有人接收这些数据库的报警,另一个是稳定性要达到99.995%。目标有了,具体怎么实现?首先,自治是一个技术的量变到质变的过程。在过去的一段时间里,我们应用了大量的新技术,包括存储计算分离,大数据处理与机器学习等等,掌握好这些技术是自治的基础。有了这些技术,还需要革新我们的思路,就像今天的电动汽车或自动驾驶,由传统厂商来制造,都显得差强人意,这一方面是思维定势,另一方面则是有它的历史包袱。我们需要破除这些,比如我们之前的数据、运维、资源都是分割开来的,所谓自动处理都是先接收一个报警,然后根据报警的内容做自动化,这明显没办法形成一个统一的整体。今天我们需要先去构建整个骨架,然后让数据、算法去丰富、去润滑整个系统。另外还需要专业知识。数据库是高度专业的系统,之前可能由DBA、内核开发人员去调校,靠数据,靠试错,靠经验。这些知识如何精确化、数字化下来,让系统也具备这些能力,是我们要去努力的事情。最后,重要的一点是要持续提升原有的基础能力,不是说我们今天智能化、自治化就是数据和算法,其他基础能力同等重要,比如OPS,我们提出了一个ad-hoc执行:假如决策模块作出了一个决策是全网内存水位高于95%的数据库实例做一个action,你要能够很快执行下去。我们目前正在向这个方向前进,预计很快我们就会对一部份数据库实例实施自治,欢迎有兴趣的同学加入一起建设,共同迎接自治时代的到来。本文作者:七幕阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 14, 2019 · 1 min · jiezi

Mars 如何分布式地执行

先前,我们已经介绍过 Mars 是什么。如今 Mars 已在 Github 开源并对内上线试用,本文将介绍 Mars 已实现的分布式执行架构,欢迎大家提出意见。架构Mars 提供了一套分布式执行 Tensor 的库。该库使用 mars.actors 实现的 Actor 模型编写,包含 Scheduler、Worker 和 Web 服务。用户向 Mars Web Service 提交的是由 Tensor 组成的 Graph。Web Service 接收这些图并提交到一台 Scheduler。在提交作业到各个 Worker 之前,Mars Scheduler 先将 Tensor 图编译成一张由 Chunk 和 Operand 组成的图,此后对图进行分析和切分。此后,Scheduler 在所有 Scheduler 中根据一致性哈希创建一系列控制单个 Operand 执行的 OperandActor。Operand 以符合拓扑序的顺序进行调度,当所有 Operand 完成执行,整张图将被标记为已完成,客户端能够从 Web 中拉取结果。整个执行过程如下图所述。作业提交用户端通过 RESTful API 向 Mars 服务提交作业。用户通过编写 Tensor 上的代码,此后通过 session.run(tensor) 将 Tensor 操作转换为 Tensor 构成的 Graph 并提交到 Web API。此后,Web API 将作业提交到 SessionActor 并在集群中创建一个 GraphActor 用于图的分析和管理。用户端则开始查询图的执行状态,直至执行结束。在 GraphActor 中,我们首先根据 chunks 设置将 Tensor 图转换为 Operand 和 Chunk 组成的图,这一过程使得图可以被进一步拆分并能够并行执行。此后,我们在图上进行一系列的分析以获得 Operand 的优先级,同时向起始 Operand 指派 Worker,关于这一部分的细节可以参考 准备执行图 章节。此后,每个 Operand 均建立一个 OperandActor 用于控制该 Operand 的具体执行。当 Operand 处于 READY状态(如同在 Operand 状态 章节描述的那样),Scheduler 将会为 Operand 选择目标 Worker,随后作业被提交 Worker 进行实际的执行。执行控制当一个 Operand 被提交到 Worker,OperandActor 等待 Worker 上的回调。如果 Operand 执行成功,Operand 的后继将被调度。如果 Operand 执行失败,OperandActor 将会尝试数次,如果仍失败则将此次执行标记为失败。取消作业用户端可以使用 RESTful API 取消运行中的作业。取消请求将被写入 Graph 的状态存储中,同时 GraphActor 上的取消接口将被调用。如果作业在准备阶段,它将在检测到停止请求后立即结束,否则请求将被下发到每个 OperandActor,并设置状态为 CANCELLING。如果此时 Operand 没有运行,Operand 状态将被直接置为 CANCELLED。如果 Operand 正在运行,停止请求将被下发到 Worker 中并导致一个 ExecutionInterrupted 错误,该错误将返回给 OperandActor,此时 Operand 的状态将被标记为 CANCELLED。准备执行图当一个 Tensor 图被提交到 Mars Scheduler,一张包含更细粒度的,由 Operand 和 Chunk 构成的图将根据数据源中包含的 chunks 参数被生成。图压缩当完成 Chunk 图的生成后,我们将会通过合并图中相邻的节点来减小图的规模,这一合并也能让我们充分利用 numexpr 这样的加速库来加速计算过程。目前 Mars 仅会合并形成单条链的 Operand。例如,当执行下面的代码import mars.tensor as mta = mt.random.rand(100, chunks=100)b = mt.random.rand(100, chunks=100)c = (a + b).sum()Mars 将会合并 Operand ADD 和 SUM 成为 FUSE 节点。RAND Operand 不会被合并,因为它们并没有和 ADD 及 SUM 组成一条简单的直线。初始 Worker 分配为 Operand 分配 Worker 对于图执行的性能而言至关重要。随机分配初始 Operand 可能导致巨大的网络开销,并有可能导致不同 Worker 间作业分配的不平衡。因为非初始节点的分配能够根据其前驱生成数据的物理分布及各个 Worker 的空闲情况方便地确定,在执行图准备阶段,我们只考虑初始 Operand 的分配问题。初始 Worker 分配需要遵循几个准则。首先,分配给每个 Worker 执行的 Operand 需要尽量保持平衡满,这能够使计算集群在整个执行阶段都有较高的利用率,这在执行的最后阶段显得尤其重要。其次,初始节点分配需要使后续节点执行时的网络”传输尽量小。也就是说,初始点分配需要充分遵循局部性原则。需要注意的是,上述准则在某些情况下会彼此冲突。一个网络传输量最小的分配方案可能会非常偏斜。我们开发了一套启发式算法来获取两个目标的平衡,该算法描述如下:选择列表中的第一个初始节点和第一台机器;从 Operand 图转换出的无向图中自该点开始进行深度优先搜索;如果另一个未被分配的初始节点被访问到,我们将其分配给步骤1中选择的机器;当访问到的 Operand 总数大于平均每个 Worker 接受的 Operand 个数时,停止分配;前往步骤1,如果仍有 Worker 未被分配 Operand,否则结束。调度策略当一个 Operand 组成的 Graph 执行时,合适的执行顺序会减少集群中暂存的数据总量,从而减小数据被 Spill 到磁盘的可能性。合适的 Worker 能够减少执行时网络传输的总量。Operand 选择策略合适的执行顺序能够显著减小集群中暂存的数据总量。下图中展示了 Tree Reduction 的例子,圆形代表 Operand,方形代表 Chunk,红色代表 Operand 正在执行,蓝色代表 Operand 可被执行,绿色代表 Operand 产生的 Chunk 已被存储,灰色代表 Operand 及其相关数据已被释放。假设我们有两台 Worker,并且每个 Operand 的资源使用量均相等,每张图展示的是不同策略下经过5个时间单元的执行后的状态。左图展示的是节点依照层次分别执行,而右图展示的是依照接近深度优先的顺序执行。左图中,有6个 Chunk 的数据需要暂存,右图只有2个。因为我们的目标是减少存储在集群中的数据总数,我们为进入 READY 状态的 Operand 设定了一套优先级策略:深度更大的 Operand 需要被优先执行;被更深的 Operand 依赖的 Operand 需要被优先执行;输出规模更小的节点需要被优先执行。Worker 选择策略当 Scheduler 准备执行图时,初始 Operand 的 Worker 已被确定。我们选择后续 Operand 分配 Worker 的依据是输入数据所在的 Worker。如果某个 Worker 拥有的输入数据大小最大,则该 Worker 将被选择用于执行后续 Operand。如果这样的 Worker 有多个,则各个候选 Worker 的资源状况将起到决定作用。Operand 状态Mars 中的每一个操作符都被一个 OperandActor 单独调度。执行的过程是一个状态转移的过程。在 OperandActor 中,我们为每一个状态的进入过程定义一个状态转移函数。起始 Operand 在初始化时位于 READY 状态,非起始 Operand 在初始化时则位于 UNSCHEDULED 状态。当给定的条件满足,Operand 将转移到另一个状态并执行相应的操作。状态转移的流程可以参考下图:我们在下面描述每个状态的含义及 Mats 在这些状态下执行的操作。UNSCHEDUED:一个 Operand 位于此状态,当它的上游数据没有准备好。READY:一个 Operand 位于此状态,当所有上游输入数据均已准备完毕。在进入这一状态时,OperandActor 向 AssignerActor 中选择的所有 Worker 提交作业。如果某一 Worker 准备运行作业,它将向 Scheduler 发送消息,Scheduler 将向其他 Worker 发送停止运行的消息,此后向该 Worker 发送消息以启动作业执行。RUNNING:一个 Operand 位于此状态,当它的执行已经启动。在进入此状态时,OperandActor 会检查作业是否已经提交。如果尚未提交,OperandActor 将构造一个由 FetchChunk Operand 和当前 Operand 组成的图,并将其提交到 Worker 中。此后,OperandActor 会在 Worker 中注册一个回调来获取作业执行完成的消息。FINISHED:一个 Operand 位于此状态,当作业执行已完成。当 Operand 进入此状态,且 Operand 无后继,一个消息将被发送到 GraphActor 以决定是否整个 Graph 的执行都已结束。与此同时,OperandActor 向它的前驱和后继发送执行完成的消息。如果一个前驱收到此消息,它将检查是否所有的后继都已执行完成。如是,当前 Operand 上的数据可以被释放。如果一个后继收到此消息,它将检查是否所有的前驱已完成。如是,该后继的状态可以转移到 READY。FREED:一个 Operand 位于此状态,当其上所有数据都已被释放。CANCELLED:一个 Operand 位于此状态,当所有重新执行的尝试均告失败。当 Operand 进入此状态,它将把相同状态传递到后继节点。CANCELLING:一个 Operand 位于此状态,当它正在被取消执行。如果此前作业正在执行,一个取消执行的请求会被发送到 Worker 上。CANCELLED:一个 Operand 位于此状态,当执行已被取消并停止运行。如果执行进入这一状态,OperandActor 会尝试将书友的后继都转为 CANCELLING。Worker 中的执行细节一个 Mars Worker 包含多个进程,以减少全局解释器锁(GIL)对执行的影响。具体的执行在独立的进程中完成。为减少不必要的内存拷贝和进程间通讯,Mars Worker 使用共享内存来存储执行结果。当一个作业被提交到 Worker,它将首先被置于队列中等待分配内存。当内存被分配后,其他 Worker 上的数据,或者当前 Worker 上已被 spill 到磁盘的数据将会被重新载入内存中。此时,所有计算需要的数据已经都在内存中,真正的计算过程将启动。当计算完成,Worker 将会把作业放到共享存储空间中。这四种执行状态的转换关系见下图。执行控制Mars Worker 通过 ExecutionActor 控制所有 Operand 在 Worker 中的执行。该 Actor 本身并不参与实际运算或者数据传输,只是向其他 Actor 提交任务。Scheduler 中的 OperandActor 通过 ExecutionActor 上的 enqueue_graph 调用向 Worker 提交作业。Worker 接受 Operand 提交并且将其换存在队列中。当作业可以执行时,ExecutionActor 将会向 Scheduler 发送消息,Scheduler 将确定是否将执行该操作。当 Scheduler 确定在当前 Worker 上执行 Operand,它将调用 start_execution 方法,并通过 add_finish_callback注册一个回调。这一设计允许执行结果被多个位置接收,这对故障恢复有价值。ExecutionActor 使用 mars.promise 模块来同时处理多个 Operand 的执行请求。具体的执行步骤通过 Promise 类的 then 方法相串联。当最终的执行结果被存储,之前注册的回调将被触发。如果在之前的任意执行步骤中发生错误,该错误会被传导到最后 catch 方法注册的处理函数中并得到处理。Operand 的排序所有在 READY 状态的 Operand 都被提交到 Scheduler 选择的 Worker 中。因此,在执行的绝大多数时间里,提交到 Operand 的 Worker 个数通常都高于单个 Worker 能够处理的 Operand 总数。因此,Worker 需要对 Operand 进行排序,此后选择一部分 Worker 来执行。这一排序过程在 TaskQueueActor 中进行,该 Actor 中维护一个优先队列,其中存储 Operand 的相关信息。与此同时,TaskQueueActor 定时运行一个作业分配任务,对处于优先队列头部的 Operand 分配执行资源直至没有多余的资源来运行 Operand,这一分配过程也会在新 Operand 提交或者 Operand 执行完成时触发。内存管理Mars Worker 管理两部分内存。第一部分是每个 Worker 进程私有的内存空间,由每个进程自己持有。第二部分是所有进程共享的内存空间,由 Apache Arrow 中的 plasma_store 持有。为了避免进程内存溢出,我们引入了 Worker 级别的 QuotaActor,用于分配进程内存。当一个 Operand 开始执行前,它将为输入和输出 Chunk 向 QuotaActor 发送批量内存请求。如果剩余的内存空间可以满足请求,该请求会被 QuotaActor 接受。否则,请求将排队等待空闲资源。当相关内存使用被释放,请求的资源会被释放,此时,QuotaActor 能够为其他 Operand 分配资源。共享内存由 plasma_store 管理,通常会占据整个内存的 50%。由于不存在溢出的可能,这部分内存无需经过 QuotaActor 而是直接通过 plasma_store 的相关方法进行分配。当共享内存使用殆尽,Mars Worker 会尝试将一部分不在使用的 Chunk spill 到磁盘中,以腾出空间容纳新的 Chunk。从共享内存 spill 到磁盘的 Chunk 数据可能会被未来的 Operand 重新使用,而从磁盘重新载入共享内存的操作可能会非常耗费 IO 资源,尤其在共享内存已经耗尽,需要 spill 其他 Chunk 到磁盘以容纳载入的 Chunk 时。因此,当数据共享并不需要时,例如该 Chunk 只会被一个 Operand 使用,我们会将 Chunk 直接载入进程私有内存中,而不是共享内存,这可以显著减少作业总执行时间。未来工作Mars 目前正在快速迭代,近期将考虑实现 Worker 级别的 failover 及 shuffle 支持,Scheduler 级别的 failover 也在计划中。本文作者:继盛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 11, 2019 · 3 min · jiezi

MongoDB 如何使用内存?为什么内存满了?

最近接到多个MongoDB内存方面的线上case及社区问题咨询,主要集中在:为什么我的 MongoDB 使用了 XX GB 内存?一个机器上部署多个 Mongod 实例/进程,WiredTiger cache 应该如何配置?MongoDB 是否应该使用 SWAP 空间来降低内存压力?MongoDB 内存用在哪?Mongod 进程启动后,除了跟普通进程一样,加载 binary、依赖的各种library 到内存,其作为一个DBMS,还需要负责客户端连接管理,请求处理,数据库元数据、存储引擎等很多工作,这些工作都涉及内存的分配与释放,默认情况下,MongoDB 使用 Google tcmalloc 作为内存分配器,内存占用的大头主要是「存储引擎」与 「客户端连接及请求的处理」。存储引擎 CacheMongoDB 3.2 及以后,默认使用 WiredTiger 存储引擎,可通过 cacheSizeGB 选项配置 WiredTiger 引擎使用内存的上限,一般建议配置在系统可用内存的60%左右(默认配置)。举个例子,如果 cacheSizeGB 配置为 10GB,可以认为 WiredTiger 引擎通过tcmalloc分配的内存总量不会超过10GB。为了控制内存的使用,WiredTiger 在内存使用接近一定阈值就会开始做淘汰,避免内存使用满了阻塞用户请求。目前有4个可配置的参数来支持 wiredtiger 存储引擎的 eviction 策略(一般不需要修改),其含义是:参数默认值含义eviction_target80当 cache used 超过 eviction_target,后台evict线程开始淘汰 CLEAN PAGEeviction_trigger95当 cache used 超过 eviction_trigger,用户线程也开始淘汰 CLEAN PAGEeviction_dirty_target5当 cache dirty 超过 eviction_dirty_target,后台evict线程开始淘汰 DIRTY PAGEeviction_dirty_trigger20当 cache dirty 超过 eviction_dirty_trigger, 用户线程也开始淘汰 DIRTY PAGE在这个规则下,一个正常运行的 MongoDB 实例,cache used 一般会在 0.8 * cacheSizeGB 及以下,偶尔超出问题不大;如果出现 used>=95% 或者 dirty>=20%,并一直持续,说明内存淘汰压力很大,用户的请求线程会阻塞参与page淘汰,请求延时就会增加,这时可以考虑「扩大内存」或者 「换更快的磁盘提升IO能力」。TCP 连接及请求处理MongoDB Driver 会跟 mongod 进程建立 tcp 连接,并在连接上发送数据库请求,接受应答,tcp 协议栈除了为连接维护socket元数据为,每个连接会有一个read buffer及write buffer,用户收发网络包,buffer的大小通过如下sysctl系统参数配置,分别是buffer的最小值、默认值以及最大值,详细解读可以google。net.ipv4.tcp_wmem = 8192 65536 16777216net.ipv4.tcp_rmem = 8192 87380 16777216redhat7(redhat6上并没有导出这么详细的信息) 上通过 ss -m 可以查看每个连接的buffer的信息,如下是一个示例,读写 buffer 分别占了 2357478bytes、2626560bytes,即均在2MB左右;500个类似的连接就会占用掉 1GB 的内存;buffer 占到多大,取决于连接上发送/应答的数据包的大小、网络质量等,如果请求应答包都很小,这个buffer也不会涨到很大;如果包比较大,这个buffer就更容易涨的很大。tcp ESTAB 0 0 127.0.0.1:51601 127.0.0.1:personal-agent skmem:(r0,rb2357478,t0,tb2626560,f0,w0,o0,bl0)除了协议栈上的内存开销,针对每个连接,Mongod 会起一个单独的线程,专门负责处理这条连接上的请求,mongod 为处理连接请求的线程配置了最大1MB的线程栈,通常实际使用在几十KB左右,通过 proc 文件系统看到这些线程栈的实际开销。 除了处理请求的线程,mongod 还有一系列的后台线程,比如主备同步、定期刷新 Journal、TTL、evict 等线程,默认每个线程最大ulimit -s(一般10MB)的线程栈,由于这批线程数量比较固定,占的内存也比较可控。# cat /proc/$pid/smaps7f563a6b2000-7f563b0b2000 rw-p 00000000 00:00 0Size: 10240 kBRss: 12 kBPss: 12 kBShared_Clean: 0 kBShared_Dirty: 0 kBPrivate_Clean: 0 kBPrivate_Dirty: 12 kBReferenced: 12 kBAnonymous: 12 kBAnonHugePages: 0 kBSwap: 0 kBKernelPageSize: 4 kBMMUPageSize: 4 kB线程在处理请求时,需要分配临时buffer存储接受到的数据包,为请求建立上下文(OperationContext),存储中间的处理结果(如排序、aggration等)以及最终的应答结果等。当有大量请求并发时,可能会观察到 mongod 使用内存上涨,等请求降下来后又慢慢释放的行为,这个主要是 tcmalloc 内存管理策略导致的,tcmalloc 为性能考虑,每个线程会有自己的 local free page cache,还有 central free page cache;内存申请时,按 local thread free page cache ==> central free page cache 查找可用内存,找不到可用内存时才会从堆上申请;当释放内存时,也会归还到 cache 里,tcmalloc 后台慢慢再归还给 OS, 默认情况下,tcmalloc 最多会 cache min(1GB,1/8 * system_memory) 的内存, 通过 setParameter.tcmallocMaxTotalThreadCacheBytesParameter 参数可以配置这个值,不过一般不建议修改,尽量在访问层面做调优)tcmalloc cache的管理策略,MongoDB 层暴露了几个参数来调整,一般不需要调整,如果能清楚的理解tcmalloc原理及参数含义,可做针对性的调优;MongoDB tcmalloc 的内存状态可以通过 db.serverStatus().tcmalloc 查看,具体含义可以看 tcmalloc 的文档。重点可以关注下 total_free_bytes ,这个值告诉你有多少内存是 tcmalloc 自己缓存着,没有归还给 OS 的。mymongo:PRIMARY&gt; db.serverStatus().tcmalloc{ “generic” : { “current_allocated_bytes” : NumberLong(“2545084352”), “heap_size” : NumberLong(“2687029248”) }, “tcmalloc” : { “pageheap_free_bytes” : 34529280, “pageheap_unmapped_bytes” : 21135360, “max_total_thread_cache_bytes” : NumberLong(1073741824), “current_total_thread_cache_bytes” : 1057800, “total_free_bytes” : 86280256, “central_cache_free_bytes” : 84363448, “transfer_cache_free_bytes” : 859008, “thread_cache_free_bytes” : 1057800, “aggressive_memory_decommit” : 0, … }}如何控制内存使用?合理配置 WiredTiger cacheSizeGB如果一个机器上只部署 Mongod,mongod 可以使用所有可用内存,则是用默认配置即可。如果机器上多个mongod混部,或者mongod跟其他的一些进程一起部署,则需要根据分给mongod的内存配额来配置 cacheSizeGB,按配额的60%左右配置即可。控制并发连接数TCP连接对 mongod 的内存开销上面已经详细分析了,很多同学对并发有一定误解,认为「并发连接数越高,数据库的QPS就越高」,实际上在大部分数据库的网络模型里,连接数过高都会使得后端内存压力变大、上下文切换开销变大,从而导致性能下降。MongoDB driver 在连接 mongod 时,会维护一个连接池(通常默认100),当有大量的客户端同时访问同一个mongod时,就需要考虑减小每个客户端连接池的大小。mongod 可以通过配置 net.maxIncomingConnections 配置项来限制最大的并发连接数量,防止数据库压力过载。是否应该配置 SWAP官方文档上的建议如下,意思是配置一下swap,避免mongod因为内存使用太多而OOM。For the WiredTiger storage engine, given sufficient memory pressure, WiredTiger may store data in swap space.Assign swap space for your systems. Allocating swap space can avoid issues with memory contention and can prevent the OOM Killer on Linux systems from killing mongod. 开启 SWAP 与否各有优劣,SWAP开启,在内存压力大的时候,会利用SWAP磁盘空间来缓解内存压力,此时整个数据库服务会变慢,但具体变慢到什么程度是不可控的。不开启SWAP,当整体内存超过机器内存上线时就会触发OOM killer把进程干掉,实际上是在告诉你,可能需要扩展一下内存资源或是优化对数据库的访问了。是否开启SWAP,实际上是在「好死」与「赖活着」的选择,个人觉得,对于一些重要的业务场景来说,首先应该为数据库规划足够的内存,当内存不足时,「及时调整扩容」比「不可控的慢」更好。其他尽量减少内存排序的场景,内存排序一般需要更多的临时内存主备节点配置差距不要过大,备节点会维护一个buffer(默认最大256MB)用于存储拉取到oplog,后台从buffer里取oplog不断重放,当备同步慢的时候,这个buffer会持续使用最大内存。控制集合及索引的数量,减少databse管理元数据的内存开销;集合、索引太多,元数据内存开销是一方面的影响,更多的会影响启动加载的效率、以及运行时的性能。本文作者:张友东阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 10, 2019 · 2 min · jiezi

阿里研究员谷朴:API 设计最佳实践的思考

API是软件系统的核心,而软件系统的复杂度Complexity是大规模软件系统能否成功最重要的因素。但复杂度Complexity并非某一个单独的问题能完全败坏的,而是在系统设计尤其是API设计层面很多很多小的设计考量一点点叠加起来的(也即John Ousterhout老爷子说的Complexity is incremental【8】)。成功的系统不是有一些特别闪光的地方,而是设计时点点滴滴的努力积累起来的。因此,这里我们试图思考并给出建议,一方面,什么样的API设计是__好__的设计?另一方面,在设计中如何能做到?API设计面临的挑战千差万别,很难有处处适用的准则,所以在讨论原则和最佳实践时,无论这些原则和最佳实践是什么,一定有适应的场景和不适应的场景。因此我们在下面争取不仅提出一些建议,也尽量去分析这些建议在什么场景下适用,这样我们也可以有针对性的采取例外的策略。范围本文偏重于__一般性的API设计__,并更适用于远程调用(RPC或者HTTP/RESTful的API),但是这里没有特别讨论RESTful API特有的一些问题。另外,本文在讨论时,假定了客户端直接和远程服务端的API交互。在阿里,由于多种原因,通过客户端的SDK来间接访问远程服务的情况更多一些。这里并不讨论SDK带来的特殊问题,但是将SDK提供的方法看作远程API的代理,这里的讨论仍然适用。API设计准则:什么是好的API在这一部分,我们试图总结一些好的API应该拥有的特性,或者说是设计的原则。这里我们试图总结更加基础性的原则。所谓基础性的原则,是那些如果我们很好的遵守了就可以让API在之后演进的过程中避免多数设计问题的原则。A good API__提供清晰的思维模型 provides a good mental model__:API是用于程序之间的交互,但是一个API如何被使用,以及API本身如何被维护,是依赖于维护者和使用者能够对该API有清晰的、一致的认识。这种状况实际上是不容易达到的。简单 is simple:“Make things as simple as possible, but no simpler.” 在实际的系统中,尤其是考虑到系统随着需求的增加不断的演化,我们绝大多数情况下见到的问题都是__过于复杂__的设计,而非过于简单,因此强调简单性一般是恰当的。容许多个实现 allows multiple implementations:这个原则看上去更具体,但是这是我非常喜欢的一个原则。这是Sanjay Ghemawat常常提到的一个原则。一般来说,在讨论API设计时常常被提到的原则是解耦性原则或者说松耦合原则。然而相比于松耦合原则,这个原则更加有可操作性:如果一个API自身可以有多个__完全不同的实现__,一般来说这个API已经有了足够好的抽象,和自身的某一个具体实现无关,那么一般也不会出现和外部系统耦合过紧的问题。因此这个原则更本质一些。最佳实践本部分则试图讨论一些更加详细、具体的建议,可以让API的设计更容易满足前面描述的基础原则。想想优秀的API例子:POSIX File API如果说API的设计实践只能列一条的话,那么可能最有帮助的和最可操作的就是这一条。本文也可以叫做“通过File API体会API设计的最佳实践”。所以整个最佳实践可以总结为一句话:“想想File API是怎么设计的。”首先回顾一下File API的主要接口(以C为例,很多是Posix API,选用比较简单的I/O接口为例【1】:int open(const char path, int oflag, …/,mode_t mode /);int close (int filedes);int remove( const char fname );ssize_t write(int fildes, const void buf, size_t nbyte);ssize_t read(int fildes, void buf, size_t nbyte);File API为什么是经典的好API设计?File API已经有几十年历史(从1988年算起将近40年),尽管期间硬件软件系统的发展经历了好几代,这套API核心保持了稳定。这是极其了不起的。API提供了非常清晰的概念模型,每个人都能够很快理解这套API背后的基础概念:什么是文件,以及相关联的操作(open, close, read, write),清晰明了;支持很多的不同文件系统实现,这些系统实现甚至于属于类型非常不同的设备,例如磁盘、块设备、管道(pipe)、共享内存、网络、终端terminal等等。这些设备有的是随机访问的,有的只支持顺序访问;有的是持久化的有的则不是。然而所有不同的设备不同的文件系统实现都可以采用了同样的接口,使得上层系统不必关注底层实现的不同,这是这套API强大的生命力的表现。例如同样是打开文件的接口,底层实现完全不同,但是通过完全一样的接口,不同的路径以及Mount机制,实现了同时支持。其他还有Procfs, pipe等。int open(const char path, int oflag, …/,mode_t mode /);例如这里的cephfs和本地文件系统,底层对应完全不同的实现,但是上层client可以不用区分对待,采用同样的接口来操作,只通过路径不同来区分。基于上面的这些原因,我们知道File API为什么能够如此成功。事实上,它是如此的成功以至于今天的-nix操作系统,everything is filed based.尽管我们有了一个非常好的例子File API,但是__要设计一个能够长期保持稳定的API是一项及其困难的事情__,因此仅有一个好的参考还不够,下面再试图展开去讨论一些更细节的问题。Document well 写详细的文档写详细的文档,并保持更新。 关于这一点,其实无需赘述,现实是,很多API的设计和维护者不重视文档的工作。在一个面向服务化/Micro-service化架构的今天,一个应用依赖大量的服务,而每个服务API又在不断的演进过程中,准确的记录每个字段和每个方法,并且保持更新,对于减少客户端的开发踩坑、减少出问题的几率,提升整体的研发效率至关重要。Carefully define the “resource” of your API 仔细的定义“资源”如果适合的话,选用“资源”加操作的方式来定义。今天很多的API都可以采用这样一个抽象的模式来定义,这种模式有很多好处,也适合于HTTP的RESTful API的设计。但是在设计API时,一个重要的前提是对Resource本身进行合理的定义。什么样的定义是合理的?Resource资源本身是对一套API操作核心对象的一个抽象Abstraction。抽象的过程是__去除细节的过程__。在我们做设计时,如果现实世界的流程或者操作对象是具体化的,抽象的Object的选择可能不那么困难,但是对于哪些细节应该包括,是需要很多思考的。例如对于文件的API,可以看出,文件File这个Resource(资源)的抽象,是“可以由一个字符串唯一标识的数据记录”。这个定义去除了文件是如何标识的(这个问题留给了各个文件系统的具体实现),也去除了关于如何存储的组织结构(again,留给了存储系统)细节。虽然我们希望API简单,但是更重要的是__选择对的实体来建模__。在底层系统设计中,我们倾向于更简单的抽象设计。有的系统里面,域模型本身的设计往往不会这么简单,需要更细致的考虑如何定义Resource。一般来说,域模型中的概念抽象,如果能和现实中的人们的体验接近,会有利于人们理解该模型。选择对的实体来建模__往往是关键。结合域模型的设计,可以参考相关的文章,例如阿白老师的文章【2】。Choose the right level of abstraction 选择合适的抽象层与前面的一个问题密切相关的,是在定义对象时需要选择合适的Level of abstraction(抽象的层级)。不同概念之间往往相互关联。仍然以File API为例。在设计这样的API时,选择抽象的层级的可能的选项有多个,例如:文本、图像混合对象“数据块” 抽象”文件“抽象这些不同的层级的抽象方式,可能描述的是同一个东西,但是在概念上是不同层面的选择。当设计一个API用于与数据访问的客户端交互时,“文件File“是更合适的抽象,而设计一个API用于文件系统内部或者设备驱动时,数据块或者数据块设备可能是合适的抽象,当设计一个文档编辑工具时,可能会用到“文本图像混合对象”这样的文件抽象层级。又例如,数据库相关的API定义,底层的抽象可能针对的是数据的存储结构,中间是数据库逻辑层需要定义数据交互的各种对象和协议,而在展示(View layer)的时候需要的抽象又有不同【3】。Prefer using different model for different layers 不同层建议采用不同的数据模型这一条与前一条密切关联,但是强调的是不同层之间模型不同。在服务化的架构下,数据对象在处理的过程中往往经历多层,例如上面的View-Logic model-Storage是典型的分层结构。在这里我们的建议是不同的Layer采用不同的数据结构。John Ousterhout 【8】书里面则更直接强调:Different layer, different abstraction。例如网络系统的7层模型,每一层有自己的协议和抽象,是个典型的例子。而前面的文件API,则是一个Logic layer的模型,而不同的文件存储实现(文件系统实现),则采用各自独立的模型(如快设备、内存文件系统、磁盘文件系统等各自有自己的存储实现API)。当API设计倾向于不同的层采用一样的模型的时候(例如一个系统使用后段存储服务与自身提供的模型之间,见下图),可能意味着这个Service本身的职责没有定义清楚,是否功能其实应该下沉?不同的层采用同样的数据结构带来的问题还在于API的演进和维护过程。一个系统演进过程中可能需要替换掉后端的存储,可能因为性能优化的关系需要分离缓存等需求,这时会发现将两个层的数据绑定一起(甚至有时候直接把前端的json存储在后端),会带来不必要的耦合而阻碍演进。Naming and identification of the resource 命名与标识当API定义了一个资源对象,下面一般需要的是提供命名/标识(Naming and identification)。在naming/ID方面,一般有两个选择(不是指系统内部的ID,而是会暴露给用户的):用free-form string作为ID(string nameAsId)用结构化数据表达naming/ID何时选择哪个方法,需要具体分析。采用Free-form string的方式定义的命名,为系统的具体实现留下了最大的自由度。带来的问题是命名的内在结构(如路径)本身并非API强制定义的一部分,转为变成实现细节。如果命名本身存在结构,客户端需要有提取结构信息的逻辑。这是一个需要做的平衡。例如文件API采用了free-form string作为文件名的标识方式,而文件的URL则是文件系统具体实现规定。这样,就容许Windows操作系统采用"D:\Documents\File.jpg"而Linux采用"/etc/init.d/file.conf"这样的结构了。而如果文件命名的数据结构定义为{ disk: string, path: string}这样结构化的方式,透出了"disk"和"path"两个部分的结构化数据,那么这样的结构可能适应于Windows的文件组织方式,而不适应于其他文件系统,也就是说泄漏了实现细节。如果资源Resource对象的抽象模型自然包含结构化的标识信息,则采用结构化方式会简化客户端与之交互的逻辑,强化概念模型。这时牺牲掉标识的灵活度,换取其他方面的优势。例如,银行的转账账号设计,可以表达为{ account: number routing: number}这样一个结构化标识,由账号和银行间标识两部分组成,这样的设计含有一定的业务逻辑在内,但是这部分业务逻辑是__被描述的系统内在逻辑而非实现细节,并且这样的设计可能有助于具体实现的简化以及避免一些非结构化的字符串标识带来的安全性问题等。因此在这里结构化的标识可能更适合。另一个相关的问题是,何时应该提供一个数字unique ID? 这是一个经常遇到的问题。有几个问题与之相关需要考虑:是否已经有结构化或者字符串的标识可以唯一、稳定标识对象?如果已经有了,那么就不一定需要numerical ID;64位整数范围够用吗?数字ID可能不是那么用户友好,对于用户来讲数字的ID会有帮助吗?如果这些问题都有答案而且不是什么阻碍,那么使用数字ID是可以的,否则要慎用数字ID。Conceptually what are the meaningful operations on this resource? 对于该对象来说,什么操作概念上是合理的?在确定下来了资源/对象以后,我们还需要定义哪些操作需要支持。这时,考虑的重点是“概念上合理(Conceptually reasonable)”。换句话说,operation + resource 连在一起听起来自然而然合理(如果Resource本身命名也比较准确的话。当然这个“如果命名准确”是个big if,非常不容易做到)。操作并不总是CRUD(create, read, update, delete)。例如,一个API的操作对象是额度(Quota),那么下面的操作听上去就比较自然:Update quota(更新额度),transfer quota(原子化的转移额度)但是如果试图Create Quota,听上去就不那么自然,因额度这样一个概念似乎表达了一个数量,概念上不需要创建。额外需要思考一下,这个对象是否真的需要创建?我们真正需要做的是什么?For update operations, prefer idempotency whenever feasible 更新操作,尽量保持幂等性Idempotency幂等性,指的是一种操作具备的性质,具有这种性质的操作可以被多次实施并且不会影响到初次实施的结果“the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application.”【3】很明显Idempotency在系统设计中会带来很多便利性,例如客户端可以更安全的重试,从而让复杂的流程实现更为简单。但是Idempotency实现并不总是很容易。Create类型的idempotency创建的Idempotency,多次调用容易出现重复创建,为实现幂等性,常见的做法是使用一个__client-side generated de-deduplication token(客户端生成的唯一ID)__,在反复重试时使用同一个Unique ID,便于服务端识别重复。Update类型的Idempotency更新值(update)类型的API,应该避免采用"Delta"语义,以便于实现幂等性。对于更新类的操作,我们再简化为两类实现方式Incremental(数量增减),如IncrementBy(3)这样的语义SetNewTotal(设置新的总量)IncrementBy 这样的语义重试的时候难以避免出错,而SetNewTotal(3)(总量设置为x)语义则比较容易具备幂等性。当然在这个例子里面,也需要看到,IncrementBy也有有点,即多个客户请求同时增加的时候,比较容易并行处理,而SetTotal可能导致并行的更新相互覆盖(或者相互阻塞)。这里,可以认为更新增量和设置新的总量这两种语义是不同的优缺点,需要根据场景来解决。如果必须优先考虑并发更新的情景,可以使用更新增量的语义,并辅助以Deduplication token解决幂等性。Delete类型idempotency:Delete的幂等性问题,往往在于一个对象被删除后,再次试图删除可能会由于数据无法被发现导致出错。这个行为一般来说也没什么问题,虽然严格意义上不幂等,但是也无副作用。如果需要实现Idempotency,系统也采用了Archive->Purge生命周期的方式分步删除,或者持久化Purge log的方式,都能支持幂等删除的实现。Compatibility 兼容API的变更需要兼容,兼容,兼容!重要的事情说三遍。这里的兼容指的是向后兼容,而兼容的定义是不会Break客户端的使用,也即__老的客户端能否正常访问服务端的新版本(如果是同一个大版本下)不会有错误的行为__。这一点对于远程的API(HTTP/RPC)尤其重要。关于兼容性,已经有很好的总结,例如【4】提供的一些建议。常见的__不兼容__变化包括(但不限于)删除一个方法、字段或者enum的数值方法、字段改名方法名称字段不改,但是语义和行为的变化,也是不兼容的。这类比较容易被忽视。更具体描述可以参加【4】。另一个关于兼容性的重要问题是,如何做不兼容的API变更?通常来说,不兼容变更需要通过一个__Deprecation process,在大版本发布时来分步骤实现__。关于Deprecation process,这里不展开描述,一般来说,需要保持过去版本的兼容性的前提下,支持新老字段/方法/语义,并给客户端足够的升级时间。这样的过程比较耗时,也正是因为如此,我们才需要如此重视API的设计。有时,一个面向内部的API升级,往往开发的同学倾向于选择高效率,采用一种叫”同步发布“的模式来做不兼容变更,即通知已知的所有的客户端,自己的服务API要做一个不兼容变更,大家一起发布,同时更新,切换到新的接口。这样的方法是非常不可取的,原因有几个:我们经常并不知道所有使用API的客户发布过程需要时间,无法真正实现“同步更新”不考虑向后兼容性的模式,一旦新的API有问题需要回滚,则会非常麻烦,这样的计划八成也不会有回滚方案,而且客户端未必都能跟着回滚。因此,对于在生产集群已经得到应用的API,强烈不建议采用“同步升级”的模式来处理不兼容API变更。Batch mutations 批量更新批量更新如何设计是另一个常见的API设计决策。这里我们常见有两种模式:客户端批量更新,或者服务端实现批量更新。如下图所示。API的设计者可能会希望实现一个服务端的批量更新能力,但是我们建议要尽量避免这样做。除非对于客户来说提供原子化+事务性的批量很有意义(all-or-nothing),否则实现服务端的批量更新有诸多的弊端,而客户端批量更新则有优势:服务端批量更新带来了API语义和实现上的复杂度。例如当部分更新成功时的语义、状态表达等即使我们希望支持批量事物,也要考虑到是否不同的后端实现都能支持事务性批量更新往往给服务端性能带来很大挑战,也容易被客户端滥用接口在客户端实现批量,可以更好的将负载由不同的服务端来承担(见图)客户端批量可以更灵活的由客户端决定失败重试策略Be aware of the risks in full replace 警惕全体替换更新模式的风险所谓Full replacement更新,是指在Mutation API中,用一个全新的Object/Resource去替换老的Object/Resource的模式。API写出来大概是这样的UpdateFoo(Foo newFoo);这是非常常见的Mutation设计模式。但是这样的模式有一些潜在的风险作为API设计者必须了解。使用Full replacement的时候,更新对象Foo在服务端可能已经有了新的成员,而客户端尚未更新并不知道该新成员。服务端增加一个新的成员一般来说是兼容的变更,但是,如果该成员之前被另一个知道这个成员的client设置了值,而这时一个不知道这个成员的client来做full-replace,该成员可能就会被覆盖。更安全的更新方式是采用Update mask,也即在API设计中引入明确的参数指明哪些成员应该被更新。UpdateFoo { Foo newFoo; boolen update_field1; // update mask boolen update_field2; // update mask}或者update mask可以用repeated “a.b.c.d“这样方式来表达。不过由于这样的API方式维护和代码实现都复杂一些,采用这样模式的API并不多。所以,本节的标题是“be aware of the risk“,而不是要求一定要用update mask。Don’t create your own error codes or error mechanism 不要试图创建自己的错误码和返回错误机制API的设计者有时很想创建自己的Error code,或者是表达返回错误的不同机制,因为每个API都有很多的细节的信息,设计者想表达出来并返回给用户,想着“用户可能会用到”。但是事实上,这么做经常只会使API变得更复杂更难用。Error-handling是用户使用API非常重要的部分。为了让用户更容易的使用API,最佳的实践应该是用标准、统一的Error Code,而不是每个API自己去创立一套。例如HTTP有规范的error code 【7】,Google Could API设计时都采用统一的Error code等【5】。为什么不建议自己创建Error code机制?Error-handling是客户端的事,而对于客户端来说,是很难关注到那么多错误的细节的,一般来说最多分两三种情况处理。往往客户端最关心的是"这个error是否应该重试(retryable)“还是应该继续向上层返回错误,而不是试图区分不同的error细节。这时多样的错误代码机制只会让处理变得复杂有人觉得提供更多的自定义的error code有助于传递信息,但是这些信息除非有系统分别处理才有意义。如果只是传递信息的话,error message里面的字段可以达到同样的效果。More更多的Design patterns,可以参考[5] Google Cloud API guide,[6] Microsoft API design best practices等。不少这里提到的问题也在这些参考的文档里面有涉及,另外他们还讨论到了像versioning,pagination,filter等常见的设计规范方面考虑。这里不再重复。参考文献【1】File wiki https://en.wikipedia.org/wiki/Computer_file【2】阿白,域模型设计系列文章,https://yq.aliyun.com/articles/6383【3】Idempotency, wiki https://en.wikipedia.org/wiki/Idempotence【4】Compatibility https://cloud.google.com/apis/design/compatibility【5】API Design patterns for Google Cloud, https://cloud.google.com/apis/design/design_patterns【6】API design best practices, Microsoft https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design【7】Http status code https://en.wikipedia.org/wiki/List_of_HTTP_status_codes【8】A philosophy of software design, John Ousterhout本文作者:jessie筱姜 阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 29, 2018 · 2 min · jiezi

一个数据库存储架构的独白

本文由云+社区发表本文作者:许中清,腾讯云自研数据库CynosDB的分布式存储CynosStore负责人。从事数据库内核开发、数据库产品架构和规划。曾就职于华为,2015年加入腾讯,参与过TBase(PGXZ)、CynosDB等数据库产品研发。专注于关系数据库、数据库集群、新型数据库架构等领域。目前担任CynosDB的分布式存储CynosStore负责人。企业IT系统迁移到公有云上已然是正在发生的趋势。数据库服务,作为公有云上提供的关键组件,是企业客户是否愿意将自己运行多年的系统搬到云上的关键考量之一。另一方面,自从System R开始,关系数据库系统已经大约四十年的历史了。尤其是随着互联网的发展,业务对数据库实例的吞吐量要求越来越高。对于很多业务来说,单个物理机器所能提供的最大吞吐量已经不能满足业务的高速发展。因此,数据库集群是很多IT系统绕不过去的坎。CynosDB for PostgreSQL是腾讯云自研的一款云原生数据库,其主要核心思想来自于亚马逊的云数据库服务Aurora。这种核心思想就是“基于日志的存储”和“存储计算分离”。同时,CynosDB在架构和工程实现上确实有很多和Aurora不一样的地方。CynosDB相比传统的单机数据库,主要解决如下问题:存算分离存算分离是云数据库区别于传统数据库的主要特点之一,主要是为了1)提升资源利用效率,用户用多少资源就给多少资源;2)计算节点无状态更有利于数据库服务的高可用性和集群管理(故障恢复、实例迁移)的便利性。存储自动扩缩容传统关系型数据库会受到单个物理机器资源的限制,包括单机上存储空间的限制和计算能力的限制。CynosDB采用分布式存储来突破单机存储限制。另外,存储支持多副本,通过RAFT协议来保证多副本的一致性。更高的网络利用率通过基于日志的存储设计思路,大幅度降低数据库运行过程中的网络流量。更高的吞吐量传统的数据库集群,面临的一个关键问题是:分布式事务和集群吞吐量线性扩展的矛盾。也就是说,很多数据库集群,要么支持完整的ACID,要么追求极好的线性扩展性,大部分时候鱼和熊掌不可兼得。前者比如Oracle RAC,是目前市场上最成熟最完善的数据库集群,提供对业务完全透明的数据访问服务。但是Oracle RAC的线性扩展性却被市场证明还不够,因此,更多用户主要用RAC来构建高可用集群,而不是高扩展的集群。后者比如Proxy+开源DB的数据库集群方案,通常能提供很好的线性扩展性,但是因为不支持分布式事务,对数据库用户存在较大的限制。又或者可以支持分布式事务,但是当跨节点写入比例很大时,反过来降低了线性扩展能力。CynosDB通过采用一写多读的方式,利用只读节点的线性扩展来提升整个系统的最大吞吐量,对于绝大部份公有云用户来说,这就已经足够了。存储自动扩缩容传统关系型数据库会受到单个物理机器资源的限制,包括单机上存储空间的限制和计算能力的限制。CynosDB采用分布式存储来突破单机存储限制。另外,存储支持多副本,通过RAFT协议来保证多副本的一致性。更高的网络利用率通过基于日志的存储设计思路,大幅度降低数据库运行过程中的网络流量。更高的吞吐量传统的数据库集群,面临的一个关键问题是:分布式事务和集群吞吐量线性扩展的矛盾。也就是说,很多数据库集群,要么支持完整的ACID,要么追求极好的线性扩展性,大部分时候鱼和熊掌不可兼得。前者比如Oracle RAC,是目前市场上最成熟最完善的数据库集群,提供对业务完全透明的数据访问服务。但是Oracle RAC的线性扩展性却被市场证明还不够,因此,更多用户主要用RAC来构建高可用集群,而不是高扩展的集群。后者比如Proxy+开源DB的数据库集群方案,通常能提供很好的线性扩展性,但是因为不支持分布式事务,对数据库用户存在较大的限制。又或者可以支持分布式事务,但是当跨节点写入比例很大时,反过来降低了线性扩展能力。CynosDB通过采用一写多读的方式,利用只读节点的线性扩展来提升整个系统的最大吞吐量,对于绝大部份公有云用户来说,这就已经足够了。下图为CynosDB for PostgreSQL的产品架构图,CynosDB是一个基于共享存储、支持一写多读的数据库集群。CynosDB for PostgreSQL产品架构图图一CynosDB for PostgreSQL产品架构图CynosDB基于CynosStore之上,CynosStore是一个分布式存储,为CynosDB提供坚实的底座。CynosStore由多个Store Node和CynosStore Client组成。CynosStore Client以二进制包的形式与DB(PostgreSQL)一起编译,为DB提供访问接口,以及负责主从DB之间的日志流传输。除此之外,每个Store Node会自动将数据和日志持续地备份到腾讯云对象存储服务COS上,用来实现PITR(即时恢复)功能。一、CynosStore数据组织形式CynosStore会为每一个数据库分配一段存储空间,我们称之为Pool,一个数据库对应一个Pool。数据库存储空间的扩缩容是通过Pool的扩缩容来实现的。一个Pool会分成多个Segment Group(SG),每个SG固定大小为10G。我们也把每个SG叫做一个逻辑分片。一个Segment Group(SG)由多个物理的Segment组成,一个Segment对应一个物理副本,多个副本通过RAFT协议来实现一致性。Segment是CynosStore中最小的数据迁移和备份单位。每个SG保存属于它的数据以及对这部分数据最近一段时间的写日志。CynosStore 数据组织形式图二 CynosStore 数据组织形式图二中CynosStore一共有3个Store Node,CynosStore中创建了一个Pool,这个Pool由3个SG组成,每个SG有3个副本。CynosStore还有空闲的副本,可以用来给当前Pool扩容,也可以创建另一个Pool,将这空闲的3个Segment组成一个SG并分配个这个新的Pool。二、基于日志异步写的分布式存储传统的数据通常采用WAL(日志先写)来实现事务和故障恢复。这样做最直观的好处是1)数据库down机后可以根据持久化的WAL来恢复数据页。2)先写日志,而不是直接写数据,可以在数据库写操作的关键路径上将随机IO(写数据页)变成顺序IO(写日志),便于提升数据库性能。基于日志的存储图三 基于日志的存储图三(左)极度抽象地描述了传统数据库写数据的过程:每次修改数据的时候,必须保证日志先持久化之后才可以对数据页进行持久化。触发日志持久化的时机通常有1)事务提交时,这个事务产生的最大日志点之前的所有日志必须持久化之后才能返回给客户端事务提交成功;2)当日志缓存空间不够用时,必须持久化之后才能释放日志缓存空间;3)当数据页缓存空间不够用时,必须淘汰部分数据页来释放缓存空间。比如根据淘汰算法必须要淘汰脏页A,那么最后修改A的日志点之前的所有日志必须先持久化,然后才可以持久化A到存储,最后才能真正从数据缓存空间中将A淘汰。从理论上来说,数据库只需要持久化日志就可以了。因为只要拥有从数据库初始化时刻到当前的所有日志,数据库就能恢复出当前任何一个数据页的内容。也就是说,数据库只需要写日志,而不需要写数据页,就能保证数据的完整性和正确性。但是,实际上数据库实现者不会这么做,因为1)从头到尾遍历日志恢复出每个数据页将是非常耗时的;2)全量日志比数据本身规模要大得多,需要更多的磁盘空间去存储。那么,如果持久化日志的存储设备不仅仅具有存储能力,还拥有计算能力,能够自行将日志重放到最新的页的话,将会怎么样?是的,如果这样的话,数据库引擎就没有必要将数据页传递给存储了,因为存储可以自行计算出新页并持久化。这就是CynosDB“采用基于日志的存储”的核心思想。图三(右)极度抽象地描述了这种思想。图中计算节点和存储节点置于不同的物理机,存储节点除了持久化日志以外,还具备通过apply日志生成最新数据页面的能力。如此一来,计算节点只需要写日志到存储节点即可,而不需要再将数据页传递给存储节点。下图描述了采用基于日志存储的CynosStore的结构。基于日志的存储图四 CynosStore:基于日志的存储此图描述了数据库引擎如何访问CynosStore。数据库引擎通过CynosStore Client来访问CynosStore。最核心的两个操作包括1)写日志;2)读数据页。数据库引擎将数据库日志传递给CynosStore,CynosStore Client负责将数据库日志转换成CynosStore Journal,并且负责将这些并发写入的Journal进行序列化,最后根据Journal修改的数据页路由到不同的SG上去,并发送给SG所属Store Node。另外,CynosStore Client采用异步的方式监听各个Store Node的日志持久化确认消息,并将归并之后的最新的持久化日志点告诉数据库引擎。当数据库引擎访问的数据页在缓存中不命中时,需要向CynosStore读取需要的页(read block)。read block是同步操作。并且,CynosStore支持一定时间范围的多版本页读取。因为各个Store Node在重放日志时的步调不能完全做到一致,总会有先有后,因此需要读请求发起者提供一致性点来保证数据库引擎所要求的一致性,或者默认情况下由CynosStore用最新的一致性点(读点)去读数据页。另外,在一写多读的场景下,只读数据库实例也需要用到CynosStore提供的多版本特性。CynosStore提供两个层面的访问接口:一个是块设备层面的接口,另一个是基于块设备的文件系统层面的接口。分别叫做CynosBS和CynosFS,他们都采用这种异步写日志、同步读数据的接口形式。那么,CynosDB for PostgreSQL,采用基于日志的存储,相比一主多从PostgreSQL集群来说,到底能带来哪些好处?1)减少网络流量。首先,只要存算分离就避免不了计算节点向存储节点发送数据。如果我们还是使用传统数据库+网络硬盘的方式来做存算分离(计算和存储介质的分离),那么网络中除了需要传递日志以外,还需要传递数据,传递数据的大小由并发写入量、数据库缓存大小、以及checkpoint频率来决定。以CynosStore作为底座的CynosDB只需要将日志传递给CynosStore就可以了,降低网络流量。2)更加有利于基于共享存储的集群的实现:一个数据库的多个实例(一写多读)访问同一个Pool。基于日志写的CynosStore能够保证只要DB主节点(读写节点)写入日志到CynosStore,就能让从节点(只读节点)能够读到被这部分日志修改过的数据页最新版本,而不需要等待主节点通过checkpoint等操作将数据页持久化到存储才能让读节点见到最新数据页。这样能够大大降低主从数据库实例之间的延时。不然,从节点需要等待主节点将数据页持久化之后(checkpoint)才能推进读点。如果这样,对于主节点来说,checkpoint的间隔太久的话,就会导致主从延时加大,如果checkpoint间隔太小,又会导致主节点写数据的网络流量增大。当然,apply日志之后的新数据页的持久化,这部分工作总是要做的,不会凭空消失,只是从数据库引擎下移到了CynosStore。但是正如前文所述,除了降低不必要的网络流量以外,CynosStore的各个SG是并行来做redo和持久化的。并且一个Pool的SG数量可以按需扩展,SG的宿主Store Node可以动态调度,因此可以用非常灵活和高效的方式来完成这部分工作。三、CynosStore Journal(CSJ)CynosStore Journal(CSJ)完成类似数据库日志的功能,比如PostgreSQL的WAL。CSJ与PostgreSQL WAL不同的地方在于:CSJ拥有自己的日志格式,与数据库语义解耦合。PostgreSQL WAL只有PostgreSQL引擎可以生成和解析,也就是说,当其他存储引擎拿到PostgreSQL WAL片段和这部分片段所修改的基础页内容,也没有办法恢复出最新的页内容。CSJ致力于定义一种与各种存储引擎逻辑无关的日志格式,便于建立一个通用的基于日志的分布式存储系统。CSJ定了5种Journal类型:1.SetByte:用Journal中的内容覆盖指定数据页中、指定偏移位置、指定长度的连续存储空间。2. SetBit:与SetByte类似,不同的是SetBit的最小粒度是Bit,例如PostgreSQL中hitbit信息,可以转换成SetBit日志。3. ClearPage:当新分配Page时,需要将其初始化,此时新分配页的原始内容并不重要,因此不需要将其从物理设备中读出来,而仅仅需要用一个全零页写入即可,ClearPage就是描述这种修改的日志类型。4. DataMove:有一些写入操作将页面中一部分的内容移动到另一个地方,DataMove类型的日志用来描述这种操作。比如PostgreSQL在Vacuum过程中对Page进行compact操作,此时用DataMove比用SetByte日志量更小。5. UserDefined:数据库引擎总会有一些操作并不会修改某个具体的页面内容,但是需要存放在日志中。比如PostgreSQL的最新的事务id(xid)就是存储在WAL中,便于数据库故障恢复时知道从那个xid开始分配。这种类型日志跟数据库引擎语义相关,不需要CynosStore去理解,但是又需要日志将其持久化。UserDefined就是来描述这种日志的。CynosStore针对这种日志只负责持久化和提供查询接口,apply CSJ时会忽略它。以上5种类型的Journal是存储最底层的日志,只要对数据的写是基于块/页的,都可以转换成这5种日志来描述。当然,也有一些引擎不太适合转换成这种最底层的日志格式,比如基于LSM的存储引擎。CSJ的另一个特点是乱序持久化,因为一个Pool的CSJ会路由到多个SG上,并且采用异步写入的方式。而每个SG返回的journal ack并不同步,并且相互穿插,因此CynosStore Client还需要将这些ack进行归并并推进连续CSJ点(VDL)。 CynosStore日志路由和乱序ACK图五 CynosStore日志路由和乱序ACK只要是连续日志根据数据分片路由,就会有日志乱序ack的问题,从而必须对日志ack进行归并。Aurora有这个机制,CynosDB同样有。为了便于理解,我们对Journal中的各个关键点的命名采用跟Aurora同样的方式。这里需要重点描述的是MTR,MTR是CynosStore提供的原子写单位,CSJ就是由一个MTR紧挨着一个MTR组成的,任意一个日志必须属于一个MTR,一个MTR中的多条日志很有可能属于不同的SG。针对PostgreSQL引擎,可以近似理解为:一个XLogRecord对应一个MTR,一个数据库事务的日志由一个或者多个MTR组成,多个数据库并发事务的MTR可以相互穿插。但是CynosStore并不理解和感知数据库引擎的事务逻辑,而只理解MTR。发送给CynosStore的读请求所提供的读点必须不能在一个MTR的内部某个日志点。简而言之,MTR就是CynosStore的事务。四、故障恢复当主实例发生故障后,有可能这个主实例上Pool中各个SG持久化的日志点在全局范围内并不连续,或者说有空洞。而这些空洞所对应的日志内容已经无从得知。比如有3条连续的日志j1, j2, j3分别路由到三个SG上,分别为sg1, sg2, sg3。在发生故障的那一刻,j1和j3已经成功发送到sg1和sg3。但是j2还在CynosStore Client所在机器的网络缓冲区中,并且随着主实例故障而丢失。那么当新的主实例启动后,这个Pool上就会有不连续的日志j1, j3,而j2已经丢失。当这种故障场景发生后,新启动的主实例将会根据上次持久化的连续日志VDL,在每个SG上查询自从这个VDL之后的所有日志,并将这些日志进行归并,计算出新的连续持久化的日志号VDL。这就是新的一致性点。新实例通过CynosStore提供的Truncate接口将每个SG上大于VDL的日志truncate掉,那么新实例产生的第一条journal将从这个新的VDL的下一条开始。故障恢复时日志恢复过程图六:故障恢复时日志恢复过程如果图五刚好是某个数据库实例故障发生的时间点,当重新启动一个数据库读写实例之后,图六就是计算新的一致性点的过程。CynosStore Client会计算得出新的一致性点就是8,并且把大于8的日志都Truncate掉。也就是把SG2上的9和10truncate掉。下一个产生的日志将会从9开始。五、多副本一致性CynosStore采用Multi-RAFT来实现SG的多副本一致性, CynosStore采用批量和异步流水线的方式来提升RAFT的吞吐量。我们采用CynosStore自定义的benchmark测得单个SG上日志持久化的吞吐量为375万条/每秒。CynosStore benchmark采用异步写入日志的方式测试CynosStore的吞吐量,日志类型包含SetByte和SetBit两种,写日志线程持续不断地写入日志,监听线程负责处理ack回包并推进VDL,然后benchmark测量单位时间内VDL的推进速度。375万条/秒意味着每秒钟一个SG持久化375万条SetByte和SetBit日志。在一个SG的场景下,CynosStore Client到Store Node的平均网络流量171MB/每秒,这也是一个Leader到一个Follower的网络流量。六、一写多读CynosDB基于共享存储CynosStore,提供对同一个Pool上的一写多读数据库实例的支持,以提升数据库的吞吐量。基于共享存储的一写多读需要解决两个问题:1. 主节点(读写节点)如何将对页的修改通知给从节点(只读节点)。因为从节点也是有Buffer的,当从节点缓存的页面在主节点中被修改时,从节点需要一种机制来得知这个被修改的消息,从而在从节点Buffer中更新这个修改或者从CynosStore中重读这个页的新版本。2. 从节点上的读请求如何读到数据库的一致性的快照。开源PostgreSQL的主备模式中,备机通过利用主机同步过来的快照信息和事务信息构造一个快照(活动事务列表)。CynosDB的从节点除了需要数据库快照(活动事务列表)以外,还需要一个CynosStore的快照(一致性读点)。因为分片的日志时并行apply的。如果一个一写多读的共享存储数据库集群的存储本身不具备日志重做的能力,主从内存页的同步有两种备选方案:第一种备选方案,主从之间只同步日志。从实例将至少需要保留主实例自从上次checkpoint以来所有产生的日志,一旦从实例产生cache miss,只能从存储上读取上次checkpoint的base页,并在此基础上重放日志缓存中自上次checkpoint以来的所有关于这个页的修改。这种方法的关键问题在于如果主实例checkpoint之间的时间间隔太长,或者日志量太大,会导致从实例在命中率不高的情况下在apply日志上耗费非常多的时间。甚至,极端场景下,导致从实例对同一个页会反复多次apply同一段日志,除了大幅增大查询时延,还产生了很多没必要的CPU开销,同时也会导致主从之间的延时有可能大幅增加。第二种备选方案,主实例向从实例提供读取内存缓冲区数据页的服务,主实例定期将被修改的页号和日志同步给从实例。当读页时,从实例首先根据主实例同步的被修改的页号信息来判断是1)直接使用从实例自己的内存页,还是2)根据内存页和日志重放新的内存页,还是3)从主实例拉取最新的内存页,还是4)从存储读取页。这种方法有点类似Oracle RAC的简化版。这种方案要解决两个关键问题:1)不同的从实例从主实例获取的页可能是不同版本,主实例内存页服务有可能需要提供多版本的能力。2)读内存页服务可能对主实例产生较大负担,因为除了多个从实例的影响以外,还有一点就是每次主实例中的某个页哪怕修改很小的一部分内容,从实例如果读到此页则必须拉取整页内容。大致来说,主实例修改越频繁,从实例拉取也会更频繁。相比较来说,CynosStore也需要同步脏页,但是CynosStore的从实例获取新页的方式要灵活的多有两种选择1)从日志重放内存页;2)从StoreNode读取。从实例对同步脏页需要的最小信息仅仅是到底哪些页被主实例给修改过,主从同步日志内容是为了让从实例加速,以及降低Store Node的负担。CynosDB一写多读图七 CynosDB一写多读图七描述了一写一读(一主一从)的基本框架,一写多读(一主多从)就是一写一读的叠加。CynosStore Client(CSClient)运行态区分主从,主CSClient源源不断地将CynosStore Journal(CSJ)从主实例发送到从实例,与开源PostgreSQL主备模式不同的是,只要这些连续的日志到达从实例,不用等到这些日志全部apply,DB engine就可以读到这些日志所修改的最新版本。从而降低主从之间的时延。这里体现“基于日志的存储”的优势:只要主实例将日志持久化到Store Node,从实例即可读到这些日志所修改的最新版本数据页。七、结语CynosStore是一个完全从零打造、适应云数据库的分布式存储。CynosStore在架构上具备一些天然优势:1)存储计算分离,并且把存储计算的网络流量降到最低; 2)提升资源利用率,降低云成本,3)更加有利于数据库实例实现一写多读,4)相比一主两从的传统RDS集群具备更高的性能。除此之外,后续我们会在性能、高可用、资源隔离等方面对CynosStore进行进一步的增强。此文已由作者授权腾讯云+社区发布 ...

December 28, 2018 · 1 min · jiezi

2018年的AI/ML惊喜及预测19年的走势(一)

摘要: 2019技术发展趋势早知道,你值得拥有!考虑到技术变革的速度,我认为让专业IT人士分享他们对2018年最大惊喜及2019年预测的看法会很有趣。以下是他们对人工智能(AI),机器学习( ML)和其他数据科学迭代的看法:CLARA分析公司首席执行官兼创始人:Chiara Lakshmikanthan2018年的惊喜:我对AI已经应用于InsureTech行业的快速步伐感到惊讶。但更重要的是,商业保险公司在其工作流程的某些部分(如承保,理赔业务和客户服务)开始使用AI以保持竞争优势。2019年的预测:在B2B 的AI领域,人们越来越关注硬实力的储蓄和价值。AI的理论价值主张被广泛接受,但是,大多数公司在未来几年对AI技术提供商的期望也将更高。Sinequa产品营销总监Scott Parker:虽然围绕ML和AI进行了大量宣传,但具有变革性的AI还有很多仍在实验室中进行测试。对于2019年,ML和AI最终会以某种方式从实验室和现有应用程序中找到出路。在大多数情况下,人们甚至不知道它在那里,因为它将以无缝的方式嵌入。数据科学家Minkyung Kang:惊喜:端到端机器学习服务使ML工作流程变得更加简单。数据科学家和开发人员可以在一个地方构建,训练和管理ML模型,并将模型大规模转移到生产环境,而无需过多担心管道和架构。预测:在ML工作流程中连接和集成不同的步骤和流程将得到进一步改进和简化,并允许许多初创公司和企业使用更少资源的ML应用程序快速移动。这将进一步扩展到ML的整个生命周期的管理,包括数据收集和管理。Anaconda的联合创始人兼首席技术官:Peter Wang惊喜:Github和Red Hat的收购,Cloudera和Hortonworks的合并也令人惊讶,它标志着Hadoop“大数据”炒作周期的终结,并清楚地表明分析和ML的未来增长必须针对异构存储架构。预测:“数据科学”作为一个领域将分成几个子专业,包括数据工程,高级统计推断和解释器,我们需要为它制定标准和最佳实践。随着我们更多地了解国家发展人工智能的力度和用传感器来完善监控状态,这将为更多的数据隐私立法提供动力。SIOS Technology总裁兼首席执行官:Jerry Melnick数据分析和人工智能将无处不在:数据分析和人工智能将继续变得更加专注,专门针对特定问题而构建,这些功能将越来越多地嵌入到云平台和管理工具中。例如,用人工智能驱动的基础设施工具现在被用于分析来自无数监测和管理工具的输入,许多这些人工智能工具都致力于解决整个IT领域的广泛问题。在2019年这些快速发展,更加专注IT人员遇到的最关键的问题及常规和复杂问题。这种备受期待的功能将简化IT运营,提高基础架构和应用程序的稳健性,并降低总体成本。随着这一趋势,人工智能和数据分析将自然地嵌入到HA和DR解决方案以及CSP产品中,以增强其运营的稳健性。通过快速,自动和准确地了解问题并诊断复杂配置中的问题,从云提供的关键应用程序服务的可靠性和可用性将大大提高。BISim高级总监:OISkar Nieder机器学习和深度学习(DL)形成的AI革命在软件开发行业中继续受到越来越多的关注。随着图形处理单元(GPU)加速的引入,以前存在的时间和计算限制被消除,新的易于使用的框架和数据中心将使这些技术在2019年向所有人提供。Python,C ++和Javascript将在2019年继续作为主要编码语言。然而,对于开发人员来说,体验TensorFlow或Caffe for AI和Angular或React等Web语言开发的语言框架将变得更加重要。Micro Focus战略总监:Mark Levy在2019年,AI和ML将与自动化融合,并将彻底改变DevOps。在过去的几年中,自动化在DevOps中的作用继续成为更大实践的一个重要方面。目前,主要的重点是自动化过程或事件驱动的手动可重复任务,但AI/ML显示变化的新进展即将出现。通过AI和ML的融合,自动化有可能展示前所未有的智能,因为新系统将关注趋势,以及分析和关联整个价值流以预测和预防问题。随着DevOps实践专注于提高运营效率,ML,AI和自动化即将融合将为使用DevOps的公司带来显着优势。Micro FocusVertica产品营销副总裁Joy King在2019年,ML项目将从科学项目和创新实验室转向由行业颠覆者领导的全面生产。事实上,每家公司都有ML项目,但其中大多数都依赖于无法访问跟业务目标相关的所有数据的专业平台。所有数据都存储在各种数据仓库和数据库中,其中没有一个能够运行端到端ML,迫使数据移动到专业平台。然而,仅使用一部分数据来训练和评分ML模型,从而导致精度有限。在2019年,当前的行业颠覆者和智能传统公司将把ML带到其所有数据,而不是将其数据转移到ML平台上。这些公司将更准确地预测结果,包括医疗设备的预测性维护,基于个性化客户行为分析的预测收入,主动检测欺诈等非服务。Portworx的联合创始人兼首席执行官Murli Thirumale人工智能和自动化将改变IT的经济方向。即使基础设施本身变得可编程,大多数DevOps仍然由人驱动。但是数据量增长如此之快,应用程序发展如此之快,这就要求基础架构必须足够灵活,这样才不会成为瓶颈。在2019年,基础设施将变得越来越可编程,基于AI的机器将预测存储和计算需求,并根据网络状况,工作负载和历史模式自动分配资源。NICE解决方案营销人员Karen Inbar机器人自动化将创造新的就业机会。随着机器人过程自动化(RPA)的出现,组织内部正在衍生出新的角色。2019年,更多公司将招聘新的专业职位和角色,如RPA工程师、RPA架构师和RPA顾问,以帮助员工了解RPA最佳实践以及RPA如何强化工作流程。随着RPA技术在工作场所变得更受欢迎和更具吸引力,“首席机器人官”等新职位也将开始出现。公司需要选择自动化哪些流程。2018年的许多自动化项目都失败了,因为它们选择了对错误的流程进行自动化。在2019年,公司需要更密切地评估任务的时间分配和复杂性,这种自动化任务的战略性重新确定优先级将确保组织在数字化转型工作中推动投资回报率和成功。一旦组织掌握了更简单的任务的自动化,他们就可以引入更先进的技术,例如光学字符识别(OCR),使无人值守的机器人能够解释更多的数据元素。WekaIO首席技术官Andy Watson到目前为止,我们知道用于ML的数据集每年都在变大,不仅是累积量,还因为信号源(相机、物联网传感器、软件日志等)的数量越来越多。我们“预测”ML研究人员将利用越来越多的功能强大的GPU来处理前所未有的大量数据。但这仅仅是对当前趋势的观察,而不是预测。相反,让我们来看看如何使用这些更大的数据体。我可以通过ML训练来预测松弛参数,以允许软件减少训练错误,对支持ML计算环境的存储基础设施将产生影响。ML的领导者DeepMind最近发表了一篇重要论文:“关系归纳偏见,深度学习和图形网络。”一个关键点是ML训练可能会发展出一种更为徒手的方法,允许其软件影响其学习途径的选择标准(通过推理模式),这将影响数据存储基础架构。在今天的任何大型数据集中,我们都有一个“工作集” - 最活跃的数据子集,最常见的是最新数据。例如,在一组ML研究人员可能累积用于培训的所有许多PB中,他们数据中心的通常情况是,从较慢的“冷”存储中只能提升几百TB的总数据库,因此他们的GPU可以在“热”快速存储层中访问它。然而,随着这种大变化,将难以确定哪个数据应该是任何给定工作集的成员。相反,将整个事物视为可能必要的可能是适当的。正在进行的各种ML事件中的每一个将从所有那些PB中选择不同,并且这将指示所有数据被放置在热层中。McAfee的首席技术战略师Candace Worley首席分析官(CAO)和首席数据官(CDO)将需要监督AI。当公司扩展AI的使用时,必须做出无数的决定。隐私监管存在影响,但也存在法律,道德和文化方面的影响,我们需要在2019年创建一个专门的角色,并对AI的使用进行执行监督。在某些情况下,AI已经表现出不利的行为,例如种族貌相,不公平地拒绝个人贷款以及错误地识别用户的基本信息。CAO和CDO将需要监督AI培训,以确保AI决策避免伤害。此外,人工智能必须接受培训,以处理真正的人类困境,优先考虑司法,问责制,透明度,同时还要检测黑客攻击和数据滥用。可解释的AI将成为一项要求,特别是对于金融/银行和医疗行业。如果AI为个人的健康或治疗提出医疗建议,医生必须能够解释用于得出该结论的逻辑和数据。我们尚未与人工智能的关系处于某种程度,许多人因为人工智能的推荐而愿意接受药物治疗或手术,特别是如果涉及的医疗专业人员无法解释其建议的“原因”。在金融行业,我们将看到使用自动分析和认知消息,根据客户需求提供有关股票,债券,房地产和其他资产的财务指导和投资建议。在这里,消费者也需要对基于AI的决策进行解释。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 24, 2018 · 1 min · jiezi

在Kubernetes上运行区块链服务(BaaS)

笔者注:本文是在2018年11月15日由Linux基金会CNCF主办的KubeCon & CloudNativeCon China 2018大会的“Running Blockchain as a Service (BaaS) on Kubernetes”演讲内容基础上整理而成,从技术上介绍了阿里云如何将基于区块链Hyperledger Fabric的BaaS和容器集群技术Kubernetes进行结合的设计理念和实践经验分享。大家好!我是来自于阿里云区块链团队的余珊,今天给大家分享的是《在Kubernetes上运行区块链服务(BaaS)》这个主题。以上是今天分享的内容大纲,其中重点在第三部分,我们将对BaaS结合Kubernetes的一些典型问题进行深入探讨。首先我们分享一下在我们眼中的区块链和BaaS的定义是什么。从狭义上来说,区块链是一种分布式共享账本技术,基于智能合约,在各参与方之间达成对交易的共识,并实现账本交易历史的不可篡改。这个定义是大家所熟知的,并且是从技术和功能上进行的概括。而从广义上来说,我们认为,区块链也是一种在机构、个人、机器之间,构建分布式信任网络、连接可信数据、实现价值流动的新的架构和协作模式。这也是跳出技术和功能维度,从更高维度去进行的理解和总结。对于另一个概念"BaaS",即"Blockchain as a Service", 我们认为,是云平台之上的区块链平台服务,提供了区块链系统的部署、运维、治理能力,以及提供了区块链应用运行和管理的能力。区块链从其类型上可分为私有链、公有链、联盟链三种类型,而从系统拓扑上我们可以将其对应为下述三种模式。对于传统的中心化系统或私有链来说,它基本属于一种星型中心化系统。对于公有链来说,是一种将所有参与企业和个人都对等连接在一起的完全去中心化系统。而对于联盟链来说,是一种带分层结构的多中心化系统。而阿里云今天主要关注的是面向企业场景的联盟链技术类型。下面我们来探讨一下为什么将区块链与容器技术以及Kubernetes进行结合。首先,我们来分析一下区块链的特点。我们将其分为区块链系统和区块链业务应用两类。区块链系统是以数据为核心、高度分布式、Full-Mesh网络拓扑、Long-Running、复杂系统类型。数据为核心:其中最重要的是账本上的数据。高度分布式:因为区块链节点可能部署于不同机房、不同region、不同国家等等。Full-Mesh: 区块链节点之间要依赖全连通的网络以实现共识、账本同步等过程。Long-Running:区块链服务和节点是长时间运行,而不是像Web应用或批处理任务那样短生命周期的。复杂系统类型:区块链系统不是一两个模块构成的简单应用,而是往往一整天解决方案或系统的形式。区块链业务应用:没有统一的标准,可能包含各种应用类型,包括无状态应用、有状态应用、Web应用、数据型应用等等类型。接下来,我们分析一下区块链结合容器技术会带来哪些优势:容器技术为区块链系统和业务应用提供了标准化的软件打包、分发的能力。容器技术实现了区块链运行环境的一致性,以及与底层基础架构的解耦,使得区块链系统和业务应用可以很方便地移植和运行在各种平台之上。进一步的,我们发现,区块链使用Kubernetes集群技术可获得以下几方面的优势:Kubernetes提供了灵活的区块链所需要的底层资源的调度能力,如计算、存储、网络等。Kubernetes强大的运维管理能力,使得我们的区块链服务的产品上线速度以及运维的效率大大提升。Kubernetes支持各种应用类型以及微服务架构,因此对于上面区块链系统和区块链业务应用各自的需求都能很好地满足。使用Kubernetes,可以更好地跟云平台进行集成,因为今天在业界它已经成为了各大云厂商云原生应用的标准底座了。Kubernetes还提供了丰富的安全和隔离功能,这对我们区块链的安全防护体系是很大的增强。另外,围绕Kubernetes有着非常活跃的社区和丰富的技术和业务生态,因此为结合区块链的研发提供了强大的技术支持和资源。这里解答图中的一个疑问,微服务架构是否适合区块链,这要结合上面的区块链特点分析来看待:对区块链系统来说,内部组件之间是强耦合、强依赖的关系,比较难解耦,内部各组件本身不是通用化的服务定位,也不是REST化服务接口,更多是例如gRPC调用,因此不是太适合微服务架构。但是对区块链业务应用来说,则很适合考虑与微服务架构进行结合。上面这幅图展示了阿里云区块链产品形态的演进历史,同时也可以看出我们在区块链结合容器以及Kubernetes方面所在的工作。在2017年10月,我们开始提供基于容器服务的区块链解决方案,支持Hyperledger Fabric,为企业提供一键式的区块链自动部署能力,当时是基于Docker Swarm集群技术。紧接着在2017年12月,我们推出了支持Kubernetes的容器服务区块链解决方案,并且在业界也是较早开始使用Helm Chart部署区块链的。在今年7月底,我们正式推出了阿里云区块链服务BaaS,支持Hyperledger Fabric,同样也是基于Kubernetes。而在今年9月杭州云栖大会上,阿里云BaaS也正式支持了蚂蚁区块链,在这背后蚂蚁区块链也通过适配改造工作实现了在Kubernetes上的部署运行。这一页展示的是阿里云BaaS的产品架构大图。其中最核心的是BaaS,目前已经支持Hyperledger Fabric和蚂蚁区块链。它们的运行实例底座都是基于阿里云容器服务Kubernetes集群。今天的演讲内容主要是围绕Hyperledger Fabric跟Kubernetes结合这方面展开讨论的。上面这一页展示了阿里云容器服务Kubernetes版的产品架构图。这里我们展示了一套跨region的Hyperledger Fabric联盟链的部署架构图。在联盟管理方的Kubernetes集群上部署了Orderer organization和Peer Organization, 而在其他业务参与方所在region的Kubernetes上部署了各自的Peer Organization. 这里的CA、Peer、Orderer、Kafka、ZooKeeper的每个实例都是用了Kubernetes的Service和Deployment类型对象来定义。此外区块链的业务应用可以部署在Kubernetes上或者其他环境上,通过SLB映射到集群worker节点的NodePort上,来访问区块链的各个service。接下来我们进入重点的第三部分,对于实现BaaS运行在Kubernetes的过程,我们曾经遇到的一些有代表性的问题,以及我们的解决思路和实践经验。首先是关于区块链BaaS的打包、发布、服务编排等方面的问题。对于以Hyperledger Fabric为代表的区块链系统来说,这方面面临的主要问题是:区块链系统本身较为复杂,在一套典型部署里可能涉及到三十多个容器、近二十个服务、十来个容器镜像;而且这些服务相互之间有较强的依赖。对于这个问题,我们的解决思路是:在打包部署方面,从一开始我们便选用了容器镜像以及Kuberentes的Helm Chart作为标准的格式和工具。这里尤其提一下,为了保证联盟链各组织创建的独立性和灵活性,我们采用的是一类组织(例如Orderer Org或Peer Org)使用一套chart的方式。在存储库管理方面,目前使用的是阿里云OSS作为Chart Repo(当然可以使用功能更丰富的如ChartMuseum等工具),使用阿里云容器镜像服务作为镜像仓库。这里我们还采用了region化的镜像仓库配置,加快大体积镜像的下载速度,同时采用imagePullSecret保护镜像的安全。在配置方式方面,我们采用了Kubernetes的ConfigMap和Secrets来存储主要的配置和安全信息,以及使用Chart Values来让管控可以根据客户的输入去定制BaaS联盟链实例。在服务编排方面,为了满足服务的依赖性需求,我们结合了Chart Template,Chart的Hook(钩子)机制,以及Kubernetes的Init Container加上Shell脚本方式,实现各种服务尤其在启动过程中的依赖和顺序保证。对于企业来说,业务系统的高可用性是非常重要的,尤其是对生产环境的系统运行和应用访问。这里我们分享一下在BaaS的每一个层面上的高可用设计思路,以及Kubernetes在其中起到怎样的帮助。首先在云基础架构和云资源服务层,我们通过云数据中心的多可用区、所依赖的云服务本身的高可用性和高可靠性来提供保障。在BaaS管控层,通过管控组件的多实例化部署避免单点故障。在容器服务的Kubernetes集群,采用3个master节点和多个worker节点的方式提供应用底座的高可用。在Hyperledger Fabric这一层,它的Orderer、Peer、Kafka、ZooKeeper、CA等类型节点均有集群或高可用互备的设计,比如任一节点挂掉的话,其他节点依然能正常提供服务。但这里有一个关键的点,就是在Kubernetes集群上部署的时候,为了避免这些本应高可用互备的Fabric节点的pod被调度到同一个worker node上,我们采用了Kubernetes Pod Anti-Affinity的功能区将高可用集群的pod调度到不同的worker上,这样保证了真正高可用的部署,提高了对故障的容忍度。在区块链业务应用层,则需要各个企业客户对应用进行周全的高可用设计和实现。在运行时,应用访问Fabric各个服务的这一环节,我们BaaS内置了云平台的SLB负载均衡能力(包含对服务端口的健康检查),以及Fabric的Service Discovery,来保证即使后端部分节点或服务不可用时,应用的调用链路都会被调度到可用的节点或服务上。下面我们谈谈BaaS数据持久化存储的问题。虽然上面已经介绍了BaaS的高可用性设计,但我们仍需考虑如何将链上账本数据、区块链关键配置等重要内容持久化保存到可靠的外部存储而不是容器内部,这样便可以在服务器节点全部发生故障,或者系统重启、备份恢复等场合依然可以实现对系统和数据的恢复。首先,作为背景,我们分析了如果使用本地盘方式可能存在的问题:Kubernetes本身对pod的调度默认并没有限定worker节点,因此如果使用本地盘,就会因为在重启或恢复过程中调度导致的pod漂移而无法读取原来worker节点上的本地盘。对于第一个问题,Kubernetes提供了NodeSelector的机制可以让pod可以绑定worker节点进行部署,不会调度到其他worker节点上,这样就可以保证能始终访问到一个本地盘。但这又带来另一个问题,即在容灾的场景,如果这个节点包括其本地盘受到损坏无法恢复时,会导致整个pod也无法恢复。因此,我们在设计BaaS中的选择是阿里云的NAS文件系统存储、以及阿里云的云盘。在数据可靠性方面,NAS和云盘可以分别提供99.999999999%和99.9999999%的数据可靠性。此外,我们都选用了SSD类型以保证I/O性能。在Kubernetes部署的时候,Fabric的节点通过Persistent Volume和Persistent Volume Claim挂载上相应的存储,并且这些存储是为每一个Fabric的业务organization独立分配的,保证了业务数据的隔离性。在和参加KubeCon大会的一些区块链用户交流的时候,有朋友提到随着账本数据的持续增长,可以怎样解决存储问题。在我们的实践中,我们发现阿里云的NAS有一些很适合区块链账本存储的一些特点:首先,阿里云NAS可提供存储容量动态无缝扩容,在这过程中Fabric节点或区块链业务应用均无需重启或停机,对存储扩容过程完全无感知。其次,有用户担心随着存储数据量的增大,存储的性能是否会明显下降。恰恰相反的是,在阿里云NAS随着所使用的数据量变得越大,NAS所提供的吞吐性能会变得更高,这样可以打消企业用户在长期生产运行方面的顾虑。在上图的右边是Fabric不同类型的区块链节点使用不同类型存储的一个示意图。接下来我们探讨一下在设计搭建BaaS联盟链跨企业的网络方面遇到的挑战。对于大多数区块链技术而言,包括Hyerpedger Fabric, 在网络上要求区块链节点之间形成Full Mesh全连通网络,以实现节点间的账本数据同步、区块广播、节点发现、交易背书等过程,同时企业也要求保障跨企业链路的安全性。对于这些需求,我们梳理了业界目前常见的几类解决方案如下,并进一步分析它们存在的一些不足之处。方案一是采用单一VPC的联盟链网络方案,在这种模式下,联盟链的所有区块链节点均被部署到一套Kubernetes集群网络或VPC内。这种方案实质上是一种私有链的模式,失去了联盟链的各方自治的价值。方案二是基于公网的联盟链网络方案,区块链节点分布式部署在不同区域,通过公网IP对外提供服务以及实现互相通信。这种方案可以较灵活、较低成本低满足大多数基本需求,但对于高级需求如企业级安全网络则不能很好地满足。方案三是基于专线互联的联盟链网络方案,它采用运营商专线方式将不同网络或数据中心进行两两互联,在业界一些企业中得到了采用。但这里面主要存在两方面的问题,首先是如果联盟链参与企业采用了不同电信运营商的专线方案的话,项目实施的复杂性和成本都会很高;其次,如果几家企业已经建好了这样一个联盟网络,对于新来的参与企业,它的接入复杂度和成本也是一个不小的问题。针对上述各种问题,我们在阿里云BaaS基础之上,结合了CEN云企业网,提供了一种安全的联盟链网络方案,主要面向高端需求的企业用户。方案的核心,是采用CEN云企业网打通不同企业的VPC网络,就像一张跨企业的环网,这样不同企业不同的VPC内的网络就可以在CEN内实现全连通。在实现网络连通之后,因为阿里云BaaS联盟链中的Peer,Orderer,CA等服务是通过域名来访问的,目的是提升应用访问的灵活性,而在CEN的这套方案中,我们可以结合云解析PrivateZone,来实现企业环网内各企业VPC之间的统一域名解析。而且上述的网络连通性和域名解析仅限于联盟内部,不会暴露到外网。除了在公共云环境之外,对于那些将区块链节点部署于本地IDC的企业来说,他们也可以通过VPN或者专线方式,接入到云上已和CEN打通的任一VPC中,便可实现和联盟任意节点的通信。作为一个小提醒,在方案实施环节,需要注意提前规划好不同VPC内的内网地址分配,避免在环网中发生冲突。这样我们便形成了一套真正跨企业、跨账户,打通各个VPC的安全联盟链网络方案。下面我们将探讨一个非常有挑战性的问题。众所周知,智能合约是区块链的一个核心。Hyperledger Fabric中的智能合约即chaincode是运行于容器当中。在上面这幅图里我们总结了Hyperledger Fabric的chaincode容器生成过程的示意图:Peer通过Docker Client发起对Docker Daemon的调用,以fabric-ccenv为基础镜像创建出一个chaincode构建容器(chaincode builder container)Peer将chaincode源代码传入chaincode构建容器,在里面完成智能合约编译Peer再调用Docker Daemon创建以fabric-baseos为基础镜像的chaincode镜像,并将在第2步编译好的chaincode二进制文件内置在chaincode镜像中。启动运行chaincode容器。从上述过程我们分析一下这里面存在的一些问题:由于该过程是独立于Kubernetes体系之外运行的,难以对chaincode容器进行生命周期管理。无法基于Kubernetes的namaspace隔离、NetworkPolicy等机制实现对chaincode容器的安全管理。针对上面分析发现的问题,我们研究了几种问题解决的思路。第一种思路,是将chaincode容器纳入到Kubernete的体系(如pod)进行管理。这在我们的角度看来,其实是最理想的方案。因为它不仅可以实现chaincode容器全生命周期与Fabric其他类型节点一致的管理方式,并且可以结合Kubernetes的NetowrkPolicy控制chaincode容器的网络访问策略。其实此前Hyperledger Fabric社区已经创建了一个相关的需求即JIRA(FAB-7406),但目前仍未实现。假设未来在此功能实现之后,我们进一步展望一下,还可以将智能合约的容器调度运行于Serverless Kubernetes之上,提供kernal级别的隔离,保证应用容器之间的安全隔离。第二种思路,如社区和网上的一些观点所提到的,将chaincode容器放入Docker-in-Docker(DIND)环境运行。这个思路背后的出发点,主要是为了降低对宿主机Docker Daemon的依赖以及动态生成chaincode镜像和容器的不可管理性。对于这个思路,我们也基于Hyperledger Fabric和Kubernetes进行了试验,在右边的这部分Kubernetes部署模板yaml代码里,绿色框的部分是用于配置DIND的容器作为peer pod的一个sidecar,同时将DIND容器内的Docker Daemon通过本地端口2375以环境变量的形式配置到peer的参数中,使得peer可以将chaincode创建相关请求发送到DIND内。通过对结果的观察和分析,我们发现了以下这几点。DIND的思路有如下一些优点:无需依赖宿主节点的/var/run/docker.sock。无需专门清理每个Kubernetes worker节点的chaincode镜像。但DIND有着一些更为明显的不足:每次创建部署或恢复peer节点会变得很慢,因为DIND内需要去拉取fabric-ccenv镜像,其大小约1.4GB;而如果用传统部署方式的话,只需在worker节点拉取一次镜像即可。Chaincode的实例化(instantiate)过程稍微变慢,推测这和DIND容器本身运行所需的开销有一定关系。当peer节点或者整个组织(organization)删掉重建之后(复用原有的数据目录),启动速度比起传统方式会慢很多,这背后的原因和第1点相同。在业界实践中,DIND方法主要用于CI/CD的场景,但对于生产环境使用的话,则在稳定性等方面仍有较多的挑战。DIND的思路仍然不能解决chaincode容器的安全访问控制和隔离的问题。第三种思路,是我们目前在BaaS中采用的方法,即综合各种配置的手段先解决最主要的问题。这包括以下几个方面的工作:首先,通过Fabric peer的合理配置(如图中右上角的示例配置)保证chaincode和peer的通信。其次,使用docker rm和docker rmi命令清理chaincode容器和镜像(它们均包含“dev-”前缀)。这里面有不同的可选位置。2.1 适合事后清理的可选位置是采用DaemonSet结合lifecycle.preStop.exec.command的位置来运行这些清理命令。2.2 适合事前清理的可选位置是在initContainer中运行上述清理命令。采用iptables规则,对chaincode容器进行网络隔离。主要是通过在Helm Chart安装阶段配置Kubernetes worker节点的iptables规则,实现限制chaincode容器对Kubernetes网络和对外部网络的访问(同时也可以限制进入chaincode容器的网络访问)。通过上述一系列手段,我们得到了对chaincode容器实现生命周期管理、安全隔离和网络访问限制的一个实用的方案。未来我们也会继续朝着思路一这种最理想方式进行更多的探索。今天阿里巴巴集团的区块链已经在多个行业、多种场景实现了结合以及业务落地,包含了如商品溯源、数字内容版权、供应链金融、数据资产共享、公益慈善、医疗处方等等。我们的客户在生产环境已经达到了百万级的交易规模以及百GB的账本数据,这也为我们提供了很丰富的区块链应用实践经验。基于这些实践,我们想跟大家分享的是,其实区块链应用设计开发并不复杂,这一页总结了构建于Kubernete之上的区块链系统和应用的基本模式。可以看到,Kubernetes帮我们解决了底层基础架构和资源的复杂性,提供了应用的标准底座;而区块链服务BaaS则帮我们解决了区块链系统配置部署和运维的复杂性,提供了统一的接口,那么对企业来说,便可以聚焦在业务流程和业务逻辑的实现,及业务应用的开发上,以及与业务数据的交互和管理上来,实现核心价值的最大化。下面,我们将进行阿里云BaaS Hyperledger Fabric的一个demo,主要展示一下几方面的过程:首先,快速创建跨企业(跨账号)、跨region的联盟链。接着,动态添加新组织、新通道,完成企业间协同,包括邀请企业,以及企业各自的审批流程。在一些关键操作点上,BaaS内置了风控保障,强制邀请短信验证才允许完成操作,这看似麻烦的环节实际上是企业对生产安全保障以及审计都非常看重和需要的。最后,我们在BaaS上部署了经典的Marbles虚拟数字资产交易的应用,包含chaincode的部署和client SDK应用的部署。最后,欢迎有兴趣的朋友进一步了解和使用阿里云的区块链服务BaaS,通过扫描图中的两个二维码可快速访问相关产品主页,申请开通免费公测试用,以及访问产品文档获得更多使用和开发指南。以上就是我今天跟大家分享的全部内容,谢谢大家!本文作者:余珊阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 19, 2018 · 1 min · jiezi

80后阿里P10,“关老板”如何带着MaxCompute一路升级?

我是个幸运的人。虽然幸运不能被复制,但是眼光和努力可以。关涛/关老板,80后的阿里P10,阿里巴巴通用计算平台负责人,阿里巴巴计算平台研究员。12年职场人生,微软和阿里的选择。关涛的花名取自谐音:观涛。有种看海观涛的闲适,但在MaxCompute技术团队里,因为团队既要做核心技术也要“落地拿结果”承担阿里云的客户规模和营收,像一个小的创业公司,因此大家更喜欢叫他”关老板”,一下子就世俗亲近了起来。关老板是个北方人,大高个也带着些书生气。因为工作的关系,带领着一支跨国团队,两岸四地奔波(太平洋两岸,北京、杭州、西雅图、加州),说话间偶尔喜欢中英文match一下。“我是一个兴趣驱动型的人,职业生涯总的来说,还算挺幸运的,做自己感兴趣的事情,走上IT这一行……”如果有认识关涛的人,应该会忍不住说上一句:这家伙,运势太好了吧。一路保送,没考过什么试,大学选择计算机的原因也很任性,喜欢玩游戏。研究生毕业后就进入了微软,是微软最年轻的技术管理者之一,后来去了阿里云,不到3年时间,已经是P10,阿里巴巴通用计算平台MaxCompute团队负责人。“特别久以前,大概初中的时候有了自己的第一台电脑,大名鼎鼎的486,带一个数学协处理器,主频266MHz,内存有4MB。”喜欢玩游戏的都知道,往往会碰见有些关卡比较难,闯不过去的情况。当时的关涛就想着:怎么能够绕开系统这些设置?于是查了很多杂志也看了很多书,试图去改游戏存档,那个阶段他第一次知道什么是十六进制,也是最初接触编程。最后自己折腾着,操纵游戏角色大杀四方,简直无敌。让程序按照自己的意愿运行的感觉,“嘿,还好玩的。”于是,开始觉得这个专业(计算机)不错。到了高中毕业的时候,因为数学竞赛被保送到南开大学,当时的一个选择是可以进数学系,南开的王牌专业,但最后,关涛还是因为兴趣选择了计算机。人生的分叉口有很多,有时候做了第1个选择,后面的路都会开始相通,看似顺势而为,其实都是选择的结果。从200公里的北京到8000多公里的西雅图工作需要定期make a little change2006年,关涛毕业了。这意味他要开始自己的职业生涯了,他有些跃跃欲试。研究生的3年,因为导师有额外要求:不能去实习,这让关涛对于招聘市场并不那么了解,对于微软同样是“没有太多的认知”。但北京有个MSRA,微软亚洲研究院,据说是当时最好的R&DCenter。抱着试试看的心态,经历了一整天的面试后,关涛顺利地拿到了offer。 他回忆:“好像也不是那么难”。在离家乡河北承德200公里远的北京,关涛一呆就是6年,是微软Bing搜索北京团队最初的几十个人之一。从偏存储层到计算层,在项目里不断地去充实自己。他是个兴趣驱动的人,但在工作中愿意变成完美主义者。在微软的第一个项目,是做一个分布式KV+ObjectStore系统,用于支持Bing搜索的图片和视频存储。2006年,还没有Hbase这样的开源系统,当时6个人的小团队完全手写一套分布式KV,最终部署在3000台机器并支持正常线上流量,在实战中接触到了分布式系统中的各种挑战,也学到了非常多的东西。“这个项目,是个好的机会与开始”。第二个项目是做搜索后台的IndexGen Pipeline:一个定制化的存储与计算系统,用于支持通用搜索100B级别的超大规模数据存储和处理,后来这个搜索后台也成为了微软Bing搜索后台的第二代架构,并服务至今。再后来就是牵头来做大数据上交互式查询(JetScopeOn Cosmos),最后基本微软一半以上的团队都在用这个系统。在关涛看来,不管是生活还是职业发展,定期去make a little change是很好的选择,保持新鲜感的同时,能看到学到更多的东西。从被别人带着写代码、到自己独立负责一些板块,再到自己带项目小组、带大一点的技术团队,这些都需要有一个自我时间界定,把握自己的发展节奏。6年微软后,他也准备make a bigger change:申请去了美国西雅图的微软总部。8000多公里以外的城市,冬天不太冷,夏天不太热,还有他最爱的单板滑雪,以至于一直坚持在每年的最后一天自驾去不同的滑雪地。在美国期间,关涛继续深入做交互式查询、StructuredData优化推动等,也积累了很多跨国技术团队管理的经验。 “美国有近40年的历史,团队成员比北京的团队更资深一些,在美国能够看到不一样的人,看到不一样的项目。”而在微软的10年时间里,关涛也关注到了国内以BAT为代表的本土企业,他们发展的很好,而且有更高的加速度……西雅图分部第22号员工10年后的回归,面对更多的挑战“当时海外办公室刚建起来,我是阿里西雅图分部的第22号员工。”“在微软10年,国内是什么情况?”好奇心不断膨胀,于是在一次偶然的机会,关涛跳去了阿里,成为了阿里巴巴通用计算平台MaxCompute团队里的一员。这是2016年1月。MaxCompute的前身是ODPS,阿里内部统一的大数据平台,目前99%的数据存储以及95%的计算能力都在这个平台上产生,如果把阿里巴巴集团的数据体系比作航母战斗群,那么MaxCompute就是中间的航空母舰。面对这样一个已经发展了近6年的相对成熟、体量极为庞大的平台,挑战非常多。而2016年1月入职阿里,2016年年会上就接过了MaxCompute的掌舵者位置,从0到1已经做完了,如何做到从1到10?留给关涛的时间并不多。他认为,大型系统逐步发展,是一个不断自我进化的过程,大数据系统也不例外。微软的经历给了他一些帮助:包括同样都是大数据引擎(规模上有较大差异),之前的技术和工程经验都能复用。而丰富的跨国技术团队管理经验也让关涛更加适应阿里的工作。**从MaxCompute1.0到MaxCompute2.0“我们是在飞行的飞机上换引擎”**关涛回忆:“当时进来的时候,MaxCompute1.0 其实是在一个技术的成熟期上,承接了阿里巴巴内部和阿里云的核心业务,而引擎升级有技术风险和问题(我们称为Regression,包括功能和性能的)。为了保证对上层透明,我们先做了一个框架升级,支持把引擎的不同版本同时部署在线上,一点一点地把流量切过来,同时观察效果。”之后再进行引擎层面的大手术。有点像是“在飞行的飞机上换引擎”。如今的MaxCompute2.0相较于1.0版本,规模达到近10万台,性能提升超过1倍以上,每年为阿里巴巴节省预算超过20亿,同时也让阿里的大数据引擎可以在未来3-5年架构上有个相对好的布局。技术团队如何管理关涛的看法是:技术管理者归根结底还是一个管理者。1、首先考虑的不是自己要做什么事情而是帮助团队做什么事情,更多的有一种“利他”的责任感。2、技术前瞻性,技术团队管理者是要带着团队有目标地、正确地往前走,把握未来方向非常重要。3、招聘层面,思考如何招到合适的人,如何进行人才布局。现在是人才在哪办公地点就在哪的阶段。从大数据角度看阿里双十一要支持好双十一,先从两个统一说起(数据统一和资源统一)。数据具有1+1大于2的特性,不同的数据融合计算能产生更大的价值。而关键就在于如何把数据都打通。几年前阿里巴巴建设中台,把内部所有的数据放在一起(物理上分布在多地的近10万台服务器上,但逻辑上统一,数据的分布和调度对用户透明),让丰富的数据帮助产品、业务前进。资源的统一化:把所有机器放在一个大的资源池里(内部称为混布项目),资源调度系统打通,对于机器的效率优化和整个系统的容灾都有非常大的帮助。做大数据的都了解,数据可以3年翻5倍,机器却不行,否则成本太高,不现实。而利用已有的服务器进行混合部署,“这也是近一年,我们重点投资的一个项目,也就是把不同BU、不同种类的机器部署在同一个资源池中。”有了这两个统一架构的前提,双十一在洪峰来临的时候,可以选择把不那么重要的工作先停掉(在百万级别的作业中基于优先级和依赖做调度),让这些机器都用来支撑洪峰。洪峰过后,又把机器主力转移到计算上,把需要的计算尽快地输出来。今年双十一,大数据集群在流量洪峰最高的几个小时,通过弹性支持了超过1/4的交易业务流量。不增加棋子,仅依靠挪动棋盘上的子,就完成布局守住将军。当然,在此之前,团队把MaxCompute已经从1.0版本切到了2.0版本,性能的提升也是支持双十一数据量的关键。在硬件只增加不到三分之一的基础上,处理数据相较去年翻了一番,达到单日处理600PB的规模。可以说,MaxCompute在这一战役中发挥得不错,甚至比去年更为优秀。**未来:云化、新硬件、非结构化计算、非关系型计算、AI是趋势DBA或将被淘汰?**去年的时候,原阿里云总裁胡晓明说:“互联网的云计算竞争是世界寡头经济的全面竞争,在我看来,就是杭州和西雅图的竞争。谁拥抱技术,谁就拥抱未来。”场主深以为然。关涛认为:目前云计算已经从互联网企业向传统企业蔓延,例如杭州的城市大脑和“最多跑一次“项目,是2G(To Government)的项目。还有基于工业大脑的工业4.0项目等。从目前的市场态度来看,企业或许可以更加开放一些,欢迎和拥抱这种技术变化,完成自我的数字化转型。“云计算不会是寡头反而会是普惠”,关涛说。前瞻话题:大数据处理领域,未来程序员应该关注什么东西?1、 新硬件的发展计算层面越来越与新硬件的创新紧密结合,硬件会带来平台革命。例如芯片类的CPU(AVX、SIMD)、ARM众核架构、GPU,FPGA,ASIC,存储类的NVM、SSD、SRM,网络类的智能网卡和RDMA等新硬件的发展,新硬件与软件的配合是值得关注的发展方向。2、 非关系型计算领域(图计算)有很多机会大数据现在还是在关系型的处理层面,包括流和批都是基于关系型数据的计算,事实上,现在非关系的计算越来越流行了,包括知识图谱、画像等越来越有价值,这些数据组织不是关系型表达,而是以点边的形式用图的方式表达,更符合物理抽象,比如人和货的关系,在风控层面,知识图谱层面,用来描述物理实体的关系更合适。明年初,将会推出MaxCompute的图计算系统MaxGraph,支持图存储、查询、模式匹配和GraphEmbedding等机器学习运算。3、 非结构化数据将变成大数据的主流越来越多的短视频、图片、语音类数据,并随着IoT的发展,可能占据80%的数据量,由于这类数据的特性在于结构各不相同,且数据非常大但是单位价值不高(相比传统结构化数据),如何快速高效的解析和处理非结构化数据,是计算平台的关键挑战。去年的时候MaxCompute发布了一个非结构化数据处理模块,能够用户自定义的方式处理包括视频音频在内的数据。4、 Al for Everything(also for BigData)DBA或将被淘汰?大数据的特点是大,不仅仅是包括数据的处理规模,还包括了整个的海量数据的管理和优化。传统数据库领域依靠DBA人力去管理的模式将不再适用。用Al优化数据分布、数据管理、做计算优化和成本优化(例如自动SubQuery合并,智能索引建立等)。“让大数据无人驾驶”,这也是未来的趋势。本文作者:晋恒阅读原文本文来自养码场专访,转发需养码场授权。

December 14, 2018 · 1 min · jiezi

如何创建一个数据科学项目?

摘要: 在一个新的数据科学项目,你应该如何组织你的项目流程?数据和代码要放在那里?应该使用什么工具?在对数据处理之前,需要考虑哪些方面?读完本文,会让你拥有一个更加科学的工作流程。假如你想要开始一个新的数据科学项目,比如对数据集进行简单的分析,或者是一个复杂的项目。你应该如何组织你的项目流程?数据和代码要放在那里?应该使用什么工具?在对数据处理之前,需要考虑哪些方面?数据科学是当前一个不太成熟的行业,每个人都各成一家。虽然我们可以在网上参照各种模板项目、文章、博客等创建一个数据科学项目,但是目前也没有教科书对这些知识做一个统一的回答。每个数据科学家都是从经验和错误中不断的探索和学习。现在,我逐渐了解到什么是典型的“数据科学项目”,应该如何构建项目?需要使用什么工具?在这篇文章中,我希望把我的经验分享给你。工作流程尽管数据科学项目的目标、规模及技术所涉及的范围很广,但其基本流程大致如下:如上图所示,项目不同,其侧重点也会有所不同:有些项目的某个过程可能特别复杂,而另一些项目可能就不需要某一过程。举个例子来说,数据科学分析项目通常就不需要“部署”(Deployment)和“监控”(Monitoring)这两个过程。现在,我们逐一来细说各个过程。源数据访问不管是你接触到人类基因组还是iris.csv,通常都会有 “原始源数据”这一概念。数据有很多种形式,可以是固定的,也可以是动态变化的,可以存储在本地或云端。其第一步都是对源数据访问,如下所示:源数据是*.csv文件集合。使用Cookiecutter工具在项目的根文件夹中创建一个data/raw/子目录,并将所有的文件存储在这里;创建docs/data.rst文件描述源数据的含义。源数据是*.csv文件集合。启动SQL服务器,创建一个raw表,将所有的CSV文件作为单独的表导入。创建docs/data.rst文件描述源数据及SQL Server位置。源数据是基因组序列文件、患者记录、excel及word文档组合等,后续还会以不可预测的方式增长。这样可以在云服务器中创建SQL数据库,将表导入。你可以在data/raw/目录存储特别大的基因组序列,在data/raw/unprocessed目录存储excel和word文件;还可以使用DVC创建Amazon S3存储器,并将data/raw/目录推送过去;也可以创建一个Python包来访问外部网站;创建docs/data.rst目录,指定SQL服务器、S3存储器和外部网站。源数据中包含不断更新的网站日志。可以使用ELK stack 并配置网站以流式传输新日志。源数据包含10万张大小为128128像素的彩色图像,所有图像的大小则为100,0001281283,将其保存在HDF5文件images.h5中。创建一个Quilt数据包并将其推送给自己的私人Quilt存储库;创建/docs/data.rst文件,为了使用数据,必须首先使用quilt install mypkg/images导入工作区,然后再使用 from quilt.data.mypkg import images导入到代码中。源数据是模拟数据集。将数据集生成实现为Python类,并在README.txt文件中记录其使用。通常来说,在设置数据源的时候可以遵循以下规则:存储数据的方式有意义,另外还要方便查询、索引。保证数据易于共享,可以使用NFS分区、Amazon S3存储器、Git-LFS存储器、Quilt包等。确保源数据是只读状态,且要备份副本。花一定的时间,记录下所有数据的含义、位置及访问过程。上面这个步骤很重要。后续项目会你可能会犯任何错误,比如源文件无效、误用方法等等,如果没有记住数据的含义、位置及访问过程,那将很麻烦。数据处理数据处理的目的是将数据转化为“干净”的数据,以便建模。在多数情况下,这种“干净”的形式就是一个特征表,因此,“数据处理”通常归结为各种形式的特征工程(feature engineering),其核心要求是:确保特征工程的逻辑可维护,目标数据集可重现,整个管道可以追溯到源数据表述。计算图(computation graph)即满足以上要求。具体例子如下:根据cookiecutter-data-science规则,使用Makefile来描述计算图。通过脚本实现每个步骤,该脚本将一些数据文件作为输入,然后输出一个新的数据文件并存储在项目的data/interim或data/processed目录中。可以使用 make -j <njobs>命令进行并行运算。使用DVC来描述和执行计算图,其过程与上面类似,此外还有共享生成文件等功能。还可以使用Luigi、Airflow或其他专用工作流管理系统来描述和执行计算图。除此之外,还可以在基于web的精美仪表板上查看计算进度。所有源数据都以表的形式存储在SQL数据库中,在SQL视图中实现所有的特征提取逻辑。此外,还可以使用SQL视图来描述对象的样本。然后,你可以根据这些特征和样本视图创建最终的模型数据集。首先,允许用户轻松的跟踪当前所定义的特征,而不用存储在大型数据表中。特征定义仅在代码运行期间有效;其次,模型从部署到生产非常简单,假设实时数据库使用相同的模式,你就只需要复制相应的视图。此外,还可以使用CTE语句将所有的特征定义编译为模型最终预测的单个查询语句。在进行数据处理时,请注意一下问题:1.重复以计算图的形式处理数据。2.考虑计算基础架构。是否进行长时间计算?是否需要并行计算还是聚类?是否可以从具有跟踪任务执行的管理UI作业中获益?3.如果想要将模型部署到生产环境中,请确保系统支持该用例。如果正在开发一个包含JAVA Android应用程序模型,但是还是想用Python开发,为了避免不必要的麻烦,就可以使用一个专门设计的DSL,然后将这个DSL转换为Java或PMML之类的中间格式。4.考虑存储特征或临时计算的元数据。可以将每个特征列保存在单独的文件中,或使用Python函数注释。建模完成数据处理和特征设计后即可开始进行建模。在一些数据科学项目中,建模可以归结为单个m.fit(X,y)或某个按钮;而在其他项目中则可能会涉及数周的迭代和实验。通常来说,你可以从“特征工程”建模开始,当模型的输出构成了很多特征时,数据处理和建模这两个过程并没有明确的界限,它们都涉及到计算。尽管如此,将建模单独列出来作为一个步骤,仍然很有意义,因为这往往会涉及到一个特殊的需求:实验管理(experiment management)。具体例子如下:如果你正在训练一个模型,用于在iris.csv数据集中对Irises进行分类。你需要尝试十个左右的标准sklearn模型,每个模型都有多个不同的参数值,并且测试不同的特征子集。如果你正在设计一个基于神经网络的图像分类模型。你可以使用ModelDB(或其他实验管理工具,如TensorBoard,Sacred,FGLab,Hyperdash,FloydHub,Comet.ML,DatMo,MLFlow,…)来记录学习曲线和实验结果,以便选择最佳的模型。使用Makefile(或DVC、工作流引擎)实现整个管道。模型训练只是计算图中的一个步骤,它输出model-<id>.pkl 文件,将模型最终AUC值附加到CSV文件,并创建 model-<id>.html报告,还有一堆用于评估的模型性能报告。实验管理/模型版本控制的UI外观如下:模型部署在实际应用中,模型最终都要部署到生产环境中,一定要有一个有效的计划,下面有些例子:建模管道输出一个训练过模型的pickle文件。所有的数据访问和特征工程代码都是由一系列Python函数实现。你需要做的就是将模型部署到Python应用程序中,创建一个包含必要函数和模型pickle文件的Python包。管建模道输出一个训练过的模型的pickle文件。部署模型需要使用Flask创建一个REST服务将其打包为一个docker容器,并通过公司的Kubernetes云服务器提供服务。训练管道生成TensorFlow模型。可以将TensorFlow服务当做REST服务。每次更新模型时,都要创建测试并运行。训练管道生成PMML文件。你可以用Java中的JPMML库来读取,一定要确保PMML导出器中要有模型测试。训练管道将模型编译为SQL查询,将SQL查询编码到应用程序中。我们对模型部署做一下总结:1.模型部署的方式有很多种。在部署之前一定要了解实际情况,并提前做计划:是否需要将模型部署到其他语言编写的代码库中?如果使用REST服务,服务的负载时多少?能否进行批量预测?如果打算购买服务,费用是多少?如果决定使用PMML,那么就要确保它能够支持你的预期预处理逻辑。如果在训练期间使用第三方数据源,那么就要考虑是否在生产中能够与它们集成,以及如何在管道导出模型中对访问信息进行编码。2.模型一旦部署到生产环境,它就转变为一行行实际的代码,所以也要满足所有需求,因此,这就需要测试。在理想情况下,部署管道应该产生用于部署的模型包以及测试时需要的所有内容。模型监控将模型成功部署到生产环境,也许训练集中的输入分布与现实不同,模型需要重新练或重新校准;也许系统性能没有达到预期。因此,你需要收集模型性能的数据并对其进行监控。这就需要你设置一个可视化仪表板,具体事例如下:将模型的输入和输出保存在logstash或数据表中,设置Metabase(或Tableau,MyDBR,Grafana等)并创建可视化模型性能和校准指标报告。进一步探索和报告在整个数据科学项目中,你还需要尝试不同的假设,以生成图标和报告。这些任务与构建管道有所不同,主要体现在两个方面:首先,大部分任务不需要可再现性,即不用包含在计算图中。另外,也没必要使用模型的可重复性,在Jupyter中手动绘制图即可。其次,这些“进一步探索”的问题往往具有不可预测性:可能需要分析性能监控日志中的一个异常值;或者测试一个新的算法。这些探索会塞满你的笔记本中,团队中的其他人可能看不懂你的记录。因此按照日期排列子项目很重要。在项目中创建project目录,子文件夹命名格式为:projects/YYYY-MM-DD -项目名称。如下所示:./2017-01-19 - Training prototype/ (README, unsorted files)./2017-01-25 - Planning slides/ (README, slides, images, notebook)./2017-02-03 - LTV estimates/ README tasks/ (another set of date-ordered subfolders)./2017-02-10 - Cleanup script/ README script.py./… 50 folders more …注意,你可以根据需要自由组织每个子项目的内部目录,因为每个子项目很可能也是一个“数据科学项目”。在任何情况下,在每个子项目中都要有个README文件夹或README.txt文件,简要列出每个子项目目录的信息。如果项目列表太长,你需要重新组织项目目录,比如压缩一部分文件移动到存档文件夹中。“探索性”的任务有两种形式,即一次性分析和可重复性使用的代码,这时候建立一些约定很有必要。服务清单数据科学项目可能会依赖一些服务,可以指定提供以下9个关键服务,来描述期望:1.文件存储。任何一个数据科学项目都必须有个存储项目的地方,且需要整个团队共享。它是网络驱动器上的一个文件夹?还是Git存储库中的一个文件夹?2.数据服务。如何存储和访问数据?这里的“数据”指的是计算机读取或输出的所有内容,包括源数据、中间结果及第三方数据集访问、元数据、模型及报告等。3.版本。代码、数据、模型、报告和文档都需要有版本控制,另外一定要备份!4.元数据和文档。如何记录项目及子项目?是否有任何机器都可读的特征、脚本、数据集或模型的元数据?5.交互式计算。在交互式计算中,你选择JupyterLab、RStudio、ROOT、Octave还是Matlab?您是否为交互式并行计算设置了一个聚类(如ipyparallel或dask)?6.作业队列和调度程序。代码如何运行?是否需要安排定期维护?7.计算图。如何描述计算图并建立可重复性?8.实验管理。如何收集、查看和分析模型培训进度和结果?使用 ModelDB、Hyperdash还是 FloydHub?9.监控仪表板。如何收集和跟踪模型在生产环境中的具体表现?使用元数据库、Tableau、 PowerBI还是Grafana?最后,我总结了一个电子表格,包含了本文提到的所有工具,可自行下载使用。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

December 14, 2018 · 1 min · jiezi

Data Lake Analytics + OSS数据文件格式处理大全

前言Data Lake Analytics是Serverless化的云上交互式查询分析服务。用户可以使用标准的SQL语句,对存储在OSS、TableStore上的数据无需移动,直接进行查询分析。目前该产品已经正式登陆阿里云,欢迎大家申请试用,体验更便捷的数据分析服务。请参考https://help.aliyun.com/document_detail/70386.html 进行产品开通服务申请。在上一篇教程中,我们介绍了如何分析CSV格式的TPC-H数据集。除了纯文本文件(例如,CSV,TSV等),用户存储在OSS上的其他格式的数据文件,也可以使用Data Lake Analytics进行查询分析,包括ORC, PARQUET, JSON, RCFILE, AVRO甚至ESRI规范的地理JSON数据,还可以用正则表达式匹配的文件等。本文详细介绍如何根据存储在OSS上的文件格式使用Data Lake Analytics (下文简称 DLA)进行分析。DLA内置了各种处理文件数据的SerDe(Serialize/Deserilize的简称,目的是用于序列化和反序列化)实现,用户无需自己编写程序,基本上能选用DLA中的一款或多款SerDe来匹配您OSS上的数据文件格式。如果还不能满足您特殊文件格式的处理需求,请联系我们,尽快为您实现。1. 存储格式与SerDe用户可以依据存储在OSS上的数据文件进行建表,通过STORED AS 指定数据文件的格式。例如,CREATE EXTERNAL TABLE nation ( N_NATIONKEY INT, N_NAME STRING, N_REGIONKEY INT, N_COMMENT STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘|’ STORED AS TEXTFILE LOCATION ‘oss://test-bucket-julian-1/tpch_100m/nation’;建表成功后可以使用SHOW CREATE TABLE语句查看原始建表语句。mysql> show create table nation;+———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————–+| Result |+———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————–+| CREATE EXTERNAL TABLE nation( n_nationkey int, n_name string, n_regionkey int, n_comment string)ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘|‘STORED AS TEXTFILELOCATION ‘oss://test-bucket-julian-1/tpch_100m/nation’|+———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————–+1 row in set (1.81 sec)下表中列出了目前DLA已经支持的文件格式,当针对下列格式的文件建表时,可以直接使用STORED AS,DLA会选择合适的SERDE/INPUTFORMAT/OUTPUTFORMAT。在指定了STORED AS 的同时,还可以根据具体文件的特点,指定SerDe (用于解析数据文件并映射到DLA表),特殊的列分隔符等。后面的部分会做进一步的讲解。2. 示例2.1 CSV文件CSV文件,本质上还是纯文本文件,可以使用STORED AS TEXTFILE。列与列之间以逗号分隔,可以通过ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’ 表示。普通CSV文件例如,数据文件oss://bucket-for-testing/oss/text/cities/city.csv的内容为Beijing,China,010ShangHai,China,021Tianjin,China,022建表语句可以为CREATE EXTERNAL TABLE city ( city STRING, country STRING, code INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’ STORED AS TEXTFILE LOCATION ‘oss://bucket-for-testing/oss/text/cities’;使用OpenCSVSerde__处理引号__引用的字段OpenCSVSerde在使用时需要注意以下几点:用户可以为行的字段指定字段分隔符、字段内容引用符号和转义字符,例如:WITH SERDEPROPERTIES (“separatorChar” = “,”, “quoteChar” = “`”, “escapeChar” = "" );不支持字段内嵌入的行分割符;所有字段定义STRING类型;其他数据类型的处理,可以在SQL中使用函数进行转换。例如,CREATE EXTERNAL TABLE test_csv_opencsvserde ( id STRING, name STRING, location STRING, create_date STRING, create_timestamp STRING, longitude STRING, latitude STRING) ROW FORMAT SERDE ‘org.apache.hadoop.hive.serde2.OpenCSVSerde’with serdeproperties(“separatorChar”=",",“quoteChar”=""",“escapeChar”="\")STORED AS TEXTFILE LOCATION ‘oss://test-bucket-julian-1/test_csv_serde_1’;自定义分隔符需要自定义列分隔符(FIELDS TERMINATED BY),转义字符(ESCAPED BY),行结束符(LINES TERMINATED BY)。需要在建表语句中指定ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’ ESCAPED BY ‘\’ LINES TERMINATED BY ‘\n’忽略CSV文件中的HEADER在csv文件中,有时会带有HEADER信息,需要在数据读取时忽略掉这些内容。这时需要在建表语句中定义skip.header.line.count。例如,数据文件oss://my-bucket/datasets/tpch/nation_csv/nation_header.tbl的内容如下:N_NATIONKEY|N_NAME|N_REGIONKEY|N_COMMENT0|ALGERIA|0| haggle. carefully final deposits detect slyly agai|1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon|2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special |3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold|4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d|5|ETHIOPIA|0|ven packages wake quickly. regu|相应的建表语句为:CREATE EXTERNAL TABLE nation_header ( N_NATIONKEY INT, N_NAME STRING, N_REGIONKEY INT, N_COMMENT STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘|’ STORED AS TEXTFILE LOCATION ‘oss://my-bucket/datasets/tpch/nation_csv/nation_header.tbl’TBLPROPERTIES (“skip.header.line.count”=“1”);skip.header.line.count的取值x和数据文件的实际行数n有如下关系:当x<=0时,DLA在读取文件时,不会过滤掉任何信息,即全部读取;当0当x>=n时,DLA在读取文件时,会过滤掉所有的文件内容。2.2 TSV文件与CSV文件类似,TSV格式的文件也是纯文本文件,列与列之间的分隔符为Tab。例如,数据文件oss://bucket-for-testing/oss/text/cities/city.tsv的内容为Beijing China 010ShangHai China 021Tianjin China 022建表语句可以为CREATE EXTERNAL TABLE city ( city STRING, country STRING, code INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’ STORED AS TEXTFILE LOCATION ‘oss://bucket-for-testing/oss/text/cities’;2.3 多字符数据字段分割符文件假设您的数据字段的分隔符包含多个字符,可采用如下示例建表语句,其中每行的数据字段分割符为“||”,可以替换为您具体的分割符字符串。ROW FORMAT SERDE ‘org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe’with serdeproperties(“field.delim”="||")示例:CREATE EXTERNAL TABLE test_csv_multidelimit ( id STRING, name STRING, location STRING, create_date STRING, create_timestamp STRING, longitude STRING, latitude STRING) ROW FORMAT SERDE ‘org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe’with serdeproperties(“field.delim”="||")STORED AS TEXTFILE LOCATION ‘oss://bucket-for-testing/oss/text/cities/’;2.4 JSON文件DLA可以处理的JSON文件通常以纯文本的格式存储,在建表时除了要指定STORED AS TEXTFILE, 还要定义SERDE。在JSON文件中,每行必须是一个完整的JSON对象。例如,下面的文件格式是不被接受的{“id”: 123, “name”: “jack”, “c3”: “2001-02-03 12:34:56”}{“id”: 456, “name”: “rose”, “c3”: “1906-04-18 05:12:00”}{“id”: 789, “name”: “tom”, “c3”: “2001-02-03 12:34:56”}{“id”: 234, “name”: “alice”, “c3”: “1906-04-18 05:12:00”}需要改写成:{“id”: 123, “name”: “jack”, “c3”: “2001-02-03 12:34:56”}{“id”: 456, “name”: “rose”, “c3”: “1906-04-18 05:12:00”}{“id”: 789, “name”: “tom”, “c3”: “2001-02-03 12:34:56”}{“id”: 234, “name”: “alice”, “c3”: “1906-04-18 05:12:00”}不含嵌套的JSON数据建表语句可以写CREATE EXTERNAL TABLE t1 (id int, name string, c3 timestamp)STORED AS JSONLOCATION ‘oss://path/to/t1/directory’;含有嵌套的JSON文件使用struct和array结构定义嵌套的JSON数据。例如,用户原始数据(注意:无论是否嵌套,一条完整的JSON数据都只能放在一行上,才能被Data Lake Analytics处理):{ “DocId”: “Alibaba”, “User_1”: { “Id”: 1234, “Username”: “bob1234”, “Name”: “Bob”, “ShippingAddress”: { “Address1”: “969 Wenyi West St.”, “Address2”: null, “City”: “Hangzhou”, “Province”: “Zhejiang” }, “Orders”: [{ “ItemId”: 6789, “OrderDate”: “11/11/2017” }, { “ItemId”: 4352, “OrderDate”: “12/12/2017” } ] } }使用在线JSON格式化工具格式化后,数据内容如下:{ “DocId”: “Alibaba”, “User_1”: { “Id”: 1234, “Username”: “bob1234”, “Name”: “Bob”, “ShippingAddress”: { “Address1”: “969 Wenyi West St.”, “Address2”: null, “City”: “Hangzhou”, “Province”: “Zhejiang” }, “Orders”: [ { “ItemId”: 6789, “OrderDate”: “11/11/2017” }, { “ItemId”: 4352, “OrderDate”: “12/12/2017” } ] }}则建表语句可以写成如下(注意:LOCATION中指定的路径必须是JSON数据文件所在的目录,该目录下的所有JSON文件都能被识别为该表的数据):CREATE EXTERNAL TABLE json_table_1 ( docid string, user_1 struct< id:INT, username:string, name:string, shippingaddress:struct< address1:string, address2:string, city:string, province:string >, orders:array< struct< itemid:INT, orderdate:string > > >)STORED AS JSONLOCATION ‘oss://xxx/test/json/hcatalog_serde/table_1/’;对该表进行查询:select * from json_table_1;+———+—————————————————————————————————————-+| docid | user_1 |+———+—————————————————————————————————————-+| Alibaba | [1234, bob1234, Bob, [969 Wenyi West St., null, Hangzhou, Zhejiang], [[6789, 11/11/2017], [4352, 12/12/2017]]] |+———+—————————————————————————————————————-+对于struct定义的嵌套结构,可以通过“.”进行层次对象引用,对于array定义的数组结构,可以通过“[数组下标]”(注意:数组下标从1开始)进行对象引用。select DocId, User_1.Id, User_1.ShippingAddress.Address1, User_1.Orders[1].ItemIdfrom json_table_1where User_1.Username = ‘bob1234’ and User_1.Orders[2].OrderDate = ‘12/12/2017’;+———+——+——————–+——-+| DocId | id | address1 | _col3 |+———+——+——————–+——-+| Alibaba | 1234 | 969 Wenyi West St. | 6789 |+———+——+——————–+——-+使用JSON函数处理数据例如,把“value_string”的嵌套JSON值作为字符串存储:{“data_key”:“com.taobao.vipserver.domains.meta.biz.alibaba.com”,“ts”:1524550275112,“value_string”:"{"appName":"","apps":[],"checksum":"50fa0540b430904ee78dff07c7350e1c","clusterMap":{"DEFAULT":{"defCkport":80,"defIPPort":80,"healthCheckTask":null,"healthChecker":{"checkCode":200,"curlHost":"","curlPath":"/status.taobao","type":"HTTP"},"name":"DEFAULT","nodegroup":"","sitegroup":"","submask":"0.0.0.0/0","syncConfig":{"appName":"trade-ma","nodegroup":"tradema","pubLevel":"publish","role":"","site":""},"useIPPort4Check":true}},"disabledSites":[],"enableArmoryUnit":false,"enableClientBeat":false,"enableHealthCheck":true,"enabled":true,"envAndSites":"","invalidThreshold":0.6,"ipDeleteTimeout":1800000,"lastModifiedMillis":1524550275107,"localSiteCall":true,"localSiteThreshold":0.8,"name":"biz.alibaba.com","nodegroup":"","owners":["junlan.zx","张三","李四","cui.yuanc"],"protectThreshold":0,"requireSameEnv":false,"resetWeight":false,"symmetricCallType":null,"symmetricType":"warehouse","tagName":"ipGroup","tenantId":"","tenants":[],"token":"1cf0ec0c771321bb4177182757a67fb0","useSpecifiedURL":false}"}使用在线JSON格式化工具格式化后,数据内容如下:{ “data_key”: “com.taobao.vipserver.domains.meta.biz.alibaba.com”, “ts”: 1524550275112, “value_string”: “{"appName":"","apps":[],"checksum":"50fa0540b430904ee78dff07c7350e1c","clusterMap":{"DEFAULT":{"defCkport":80,"defIPPort":80,"healthCheckTask":null,"healthChecker":{"checkCode":200,"curlHost":"","curlPath":"/status.taobao","type":"HTTP"},"name":"DEFAULT","nodegroup":"","sitegroup":"","submask":"0.0.0.0/0","syncConfig":{"appName":"trade-ma","nodegroup":"tradema","pubLevel":"publish","role":"","site":""},"useIPPort4Check":true}},"disabledSites":[],"enableArmoryUnit":false,"enableClientBeat":false,"enableHealthCheck":true,"enabled":true,"envAndSites":"","invalidThreshold":0.6,"ipDeleteTimeout":1800000,"lastModifiedMillis":1524550275107,"localSiteCall":true,"localSiteThreshold":0.8,"name":"biz.alibaba.com","nodegroup":"","owners":["junlan.zx","张三","李四","cui.yuanc"],"protectThreshold":0,"requireSameEnv":false,"resetWeight":false,"symmetricCallType":null,"symmetricType":"warehouse","tagName":"ipGroup","tenantId":"","tenants":[],"token":"1cf0ec0c771321bb4177182757a67fb0","useSpecifiedURL":false}"}建表语句为CREATE external TABLE json_table_2 ( data_key string, ts bigint, value_string string)STORED AS JSONLOCATION ‘oss://xxx/test/json/hcatalog_serde/table_2/’;表建好后,可进行查询:select * from json_table_2;+—————————————————+—————+————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————+| data_key | ts | value_string |+—————————————————+—————+————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————+| com.taobao.vipserver.domains.meta.biz.alibaba.com | 1524550275112 | {“appName”:”",“apps”:[],“checksum”:“50fa0540b430904ee78dff07c7350e1c”,“clusterMap”:{“DEFAULT”:{“defCkport”:80,“defIPPort”:80,“healthCheckTask”:null,“healthChecker”:{“checkCode”:200,“curlHost”:"",“curlPath”:"/status.taobao",“type”:“HTTP”},“name”:“DEFAULT”,“nodegroup”:"",“sitegroup”:"",“submask”:“0.0.0.0/0”,“syncConfig”:{“appName”:“trade-ma”,“nodegroup”:“tradema”,“pubLevel”:“publish”,“role”:"",“site”:""},“useIPPort4Check”:true}},“disabledSites”:[],“enableArmoryUnit”:false,“enableClientBeat”:false,“enableHealthCheck”:true,“enabled”:true,“envAndSites”:"",“invalidThreshold”:0.6,“ipDeleteTimeout”:1800000,“lastModifiedMillis”:1524550275107,“localSiteCall”:true,“localSiteThreshold”:0.8,“name”:“biz.alibaba.com”,“nodegroup”:"",“owners”:[“junlan.zx”,“张三”,“李四”,“cui.yuanc”],“protectThreshold”:0,“requireSameEnv”:false,“resetWeight”:false,“symmetricCallType”:null,“symmetricType”:“warehouse”,“tagName”:“ipGroup”,“tenantId”:"",“tenants”:[],“token”:“1cf0ec0c771321bb4177182757a67fb0”,“useSpecifiedURL”:false} |+—————————————————+—————+————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————+下面SQL示例json_parse,json_extract_scalar,json_extract等常用JSON函数的使用方式:mysql> select json_extract_scalar(json_parse(value), ‘$.owners[1]’) from json_table_2;+——–+| _col0 |+——–+| 张三 |+——–+mysql> select json_extract_scalar(json_obj.json_col, ‘$.DEFAULT.submask’) from ( select json_extract(json_parse(value), ‘$.clusterMap’) as json_col from json_table_2) json_objwhere json_extract_scalar(json_obj.json_col, ‘$.DEFAULT.healthChecker.curlPath’) = ‘/status.taobao’;+———–+| _col0 |+———–+| 0.0.0.0/0 |+———–+mysql> with json_obj as (select json_extract(json_parse(value), ‘$.clusterMap’) as json_col from json_table_2)select json_extract_scalar(json_obj.json_col, ‘$.DEFAULT.submask’)from json_obj where json_extract_scalar(json_obj.json_col, ‘$.DEFAULT.healthChecker.curlPath’) = ‘/status.taobao’;+———–+| _col0 |+———–+| 0.0.0.0/0 |+———–+2.5 ORC文件Optimized Row Columnar(ORC)是Apache开源项目Hive支持的一种优化的列存储文件格式。与CSV文件相比,不仅可以节省存储空间,还可以得到更好的查询性能。对于ORC文件,只需要在建表时指定 STORED AS ORC。例如,CREATE EXTERNAL TABLE orders_orc_date ( O_ORDERKEY INT, O_CUSTKEY INT, O_ORDERSTATUS STRING, O_TOTALPRICE DOUBLE, O_ORDERDATE DATE, O_ORDERPRIORITY STRING, O_CLERK STRING, O_SHIPPRIORITY INT, O_COMMENT STRING) STORED AS ORC LOCATION ‘oss://bucket-for-testing/datasets/tpch/1x/orc_date/orders_orc’;2.6 PARQUET文件Parquet是Apache开源项目Hadoop支持的一种列存储的文件格式。使用DLA建表时,需要指定STORED AS PARQUET即可。例如,CREATE EXTERNAL TABLE orders_parquet_date ( O_ORDERKEY INT, O_CUSTKEY INT, O_ORDERSTATUS STRING, O_TOTALPRICE DOUBLE, O_ORDERDATE DATE, O_ORDERPRIORITY STRING, O_CLERK STRING, O_SHIPPRIORITY INT, O_COMMENT STRING) STORED AS PARQUET LOCATION ‘oss://bucket-for-testing/datasets/tpch/1x/parquet_date/orders_parquet’;2.7 RCFILE文件Record Columnar File (RCFile), 列存储文件,可以有效地将关系型表结构存储在分布式系统中,并且可以被高效地读取和处理。DLA在建表时,需要指定STORED AS RCFILE。例如,CREATE EXTERNAL TABLE lineitem_rcfile_date ( L_ORDERKEY INT, L_PARTKEY INT, L_SUPPKEY INT, L_LINENUMBER INT, L_QUANTITY DOUBLE, L_EXTENDEDPRICE DOUBLE, L_DISCOUNT DOUBLE, L_TAX DOUBLE, L_RETURNFLAG STRING, L_LINESTATUS STRING, L_SHIPDATE DATE, L_COMMITDATE DATE, L_RECEIPTDATE DATE, L_SHIPINSTRUCT STRING, L_SHIPMODE STRING, L_COMMENT STRING) STORED AS RCFILELOCATION ‘oss://bucke-for-testing/datasets/tpch/1x/rcfile_date/lineitem_rcfile'2.8 AVRO文件DLA针对AVRO文件建表时,需要指定STORED AS AVRO,并且定义的字段需要符合AVRO文件的schema。如果不确定可以通过使用Avro提供的工具,获得schema,并根据schema建表。在Apache Avro官网下载avro-tools-.jar到本地,执行下面的命令获得Avro文件的schema:java -jar avro-tools-1.8.2.jar getschema /path/to/your/doctors.avro{ “type” : “record”, “name” : “doctors”, “namespace” : “testing.hive.avro.serde”, “fields” : [ { “name” : “number”, “type” : “int”, “doc” : “Order of playing the role” }, { “name” : “first_name”, “type” : “string”, “doc” : “first name of actor playing role” }, { “name” : “last_name”, “type” : “string”, “doc” : “last name of actor playing role” } ]}建表语句如下,其中fields中的name对应表中的列名,type需要参考本文档中的表格转成hive支持的类型CREATE EXTERNAL TABLE doctors(number int,first_name string,last_name string)STORED AS AVROLOCATION ‘oss://mybucket-for-testing/directory/to/doctors’;大多数情况下,Avro的类型可以直接转换成Hive中对应的类型。如果该类型在Hive不支持,则会转换成接近的类型。具体请参照下表:2.9 可以用正则表达式匹配的文件通常此类型的文件是以纯文本格式存储在OSS上的,每一行代表表中的一条记录,并且每行可以用正则表达式匹配。例如,Apache WebServer日志文件就是这种类型的文件。某日志文件的内容为:127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] “GET /apache_pb.gif HTTP/1.0” 200 2326127.0.0.1 - - [26/May/2009:00:00:00 +0000] “GET /someurl/?track=Blabla(Main) HTTP/1.1” 200 5864 - “Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.65 Safari/525.19"每行文件可以用下面的正则表达式表示,列之间使用空格分隔:([^ ]) ([^ ]) ([^ ]) (-|\[[^\]]\]) ([^ "]|"[^"]") (-|[0-9]) (-|[0-9])(?: ([^ "]|"[^"]") ([^ "]|"[^"]"))?针对上面的文件格式,建表语句可以表示为:CREATE EXTERNAL TABLE serde_regex( host STRING, identity STRING, userName STRING, time STRING, request STRING, status STRING, size INT, referer STRING, agent STRING)ROW FORMAT SERDE ‘org.apache.hadoop.hive.serde2.RegexSerDe’WITH SERDEPROPERTIES ( “input.regex” = “([^ ]) ([^ ]) ([^ ]) (-|\[[^\]]\]) ([^ "]|"[^"]") (-|[0-9]) (-|[0-9])(?: ([^ "]|"[^"]") ([^ "]|"[^"]"))?")STORED AS TEXTFILELOCATION ‘oss://bucket-for-testing/datasets/serde/regex’;查询结果mysql> select * from serde_regex;+———–+———-+——-+——————————+———————————————+——–+——+———+————————————————————————————————————————–+| host | identity | userName | time | request | status | size | referer | agent |+———–+———-+——-+——————————+———————————————+——–+——+———+————————————————————————————————————————–+| 127.0.0.1 | - | frank | [10/Oct/2000:13:55:36 -0700] | “GET /apache_pb.gif HTTP/1.0” | 200 | 2326 | NULL | NULL || 127.0.0.1 | - | - | [26/May/2009:00:00:00 +0000] | “GET /someurl/?track=Blabla(Main) HTTP/1.1” | 200 | 5864 | - | “Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.65 Safari/525.19” |+———–+———-+——-+——————————+———————————————+——–+——+———+————————————————————————————————————————–+2.10 Esri ArcGIS的地理JSON数据文件DLA支持Esri ArcGIS的地理JSON数据文件的SerDe处理,关于这种地理JSON数据格式说明,可以参考:https://github.com/Esri/spatial-framework-for-hadoop/wiki/JSON-Formats示例:CREATE EXTERNAL TABLE IF NOT EXISTS california_counties( Name string, BoundaryShape binary)ROW FORMAT SERDE ‘com.esri.hadoop.hive.serde.JsonSerde’STORED AS INPUTFORMAT ‘com.esri.json.hadoop.EnclosedJsonInputFormat’OUTPUTFORMAT ‘org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat’LOCATION ‘oss://test_bucket/datasets/geospatial/california-counties/‘3. 总结通过以上例子可以看出,DLA可以支持大部分开源存储格式的文件。对于同一份数据,使用不同的存储格式,在OSS中存储文件的大小,DLA的查询分析速度上会有较大的差别。推荐使用ORC格式进行文件的存储和查询。为了获得更快的查询速度,DLA还在不断的优化中,后续也会支持更多的数据源,为用户带来更好的大数据分析体验。本文作者:金络阅读原文本文为云栖社区原创内容,未经允许不得转载。

November 23, 2018 · 5 min · jiezi

HBase 在人工智能场景的使用

近几年来,人工智能逐渐火热起来,特别是和大数据一起结合使用。人工智能的主要场景又包括图像能力、语音能力、自然语言处理能力和用户画像能力等等。这些场景我们都需要处理海量的数据,处理完的数据一般都需要存储起来,这些数据的特点主要有如下几点:大:数据量越大,对我们后面建模越会有好处;稀疏:每行数据可能拥有不同的属性,比如用户画像数据,每个人拥有属性相差很大,可能用户A拥有这个属性,但是用户B没有这个属性;那么我们希望存储的系统能够处理这种情况,没有的属性在底层不占用空间,这样可以节约大量的空间使用;列动态变化:每行数据拥有的列数是不一样的。为了更好的介绍 HBase 在人工智能场景下的使用,下面以某人工智能行业的客户案例进行分析如何利用 HBase 设计出一个快速查找人脸特征的系统。目前该公司的业务场景里面有很多人脸相关的特征数据,总共3400多万张,每张人脸数据大概 3.2k。这些人脸数据又被分成很多组,每个人脸特征属于某个组。目前总共有近62W个人脸组,每个组的人脸张数范围为 1 ~ 1W不等,每个组里面会包含同一个人不同形式的人脸数据。组和人脸的分布如下:43%左右的组含有1张人脸数据;47%左右的组含有 2 ~ 9张人脸数据;其余的组人脸数范围为 10 ~ 10000。现在的业务需求主要有以下两类:根据人脸组 id 查找该组下面的所有人脸;根据人脸组 id +人脸 id 查找某个人脸的具体数据。MySQL + OSS 方案之前业务数据量比较小的情况使用的存储主要为 MySQL 以及 OSS(对象存储)。相关表主要有人脸组表group和人脸表face。表的格式如下:group表:face表:其中 feature 大小为3.2k,是二进制数据 base64 后存入的,这个就是真实的人脸特征数据。现在人脸组 id 和人脸 id 对应关系存储在 MySQL 中,对应上面的 group 表;人脸 id 和人脸相关的特征数据存储在 OSS 里面,对应上面的 face 表。因为每个人脸组包含的人类特征数相差很大(1 ~ 1W),所以基于上面的表设计,我们需要将人脸组以及每张人脸特征id存储在每一行,那么属于同一个人脸组的数据在MySQL 里面上实际上存储了很多行。比如某个人脸组id对应的人脸特征数为1W,那么需要在 MySQL 里面存储 1W 行。我们如果需要根据人脸组 id 查找该组下面的所有人脸,那么需要从 MySQL 中读取很多行的数据,从中获取到人脸组和人脸对应的关系,然后到 OSS 里面根据人脸id获取所有人脸相关的特征数据,如下图的左部分所示。我们从上图的查询路径可以看出,这样的查询导致链路非常长。从上面的设计可看出,如果查询的组包含的人脸张数比较多的情况下,那么我们需要从 MySQL 里面扫描很多行,然后再从 OSS 里面拿到这些人脸的特征数据,整个查询时间在10s左右,远远不能满足现有业务快速发展的需求。HBase 方案上面的设计方案有两个问题:原本属于同一条数据的内容由于数据本身大小的原因无法存储到一行里面,导致后续查下需要访问两个存储系统;由于MySQL不支持动态列的特性,所以属于同一个人脸组的数据被拆成多行存储。针对上面两个问题,我们进行了分析,得出这个是 HBase 的典型场景,原因如下:HBase 拥有动态列的特性,支持万亿行,百万列;HBase 支持多版本,所有的修改都会记录在 HBase 中;HBase 2.0 引入了 MOB(Medium-Sized Object) 特性,支持小文件存储。HBase 的 MOB 特性针对文件大小在 1k10MB 范围的,比如图片,短视频,文档等,具有低延迟,读写强一致,检索能力强,水平易扩展等关键能力。我们可以使用这三个功能重新设计上面 MySQL + OSS 方案。结合上面应用场景的两大查询需求,我们可以将人脸组 id 作为 HBase 的 Rowkey,系统的设计如上图的右部分显示,在创建表的时候打开 MOB 功能,如下:create ‘face’, {NAME => ‘c’, IS_MOB => true, MOB_THRESHOLD => 2048}上面我们创建了名为 face 的表,IS_MOB 属性说明列簇 c 将启用 MOB 特性,MOB_THRESHOLD 是 MOB 文件大小的阈值,单位是字节,这里的设置说明文件大于 2k 的列都当做小文件存储。大家可能注意到上面原始方案中采用了 OSS 对象存储,那我们为什么不直接使用 OSS 存储人脸特征数据呢,如果有这个疑问,可以看看下面表的性能测试:根据上面的对比,使用 HBase MOB特性来存储小于10MB的对象相比直接使用对象存储有一些优势。我们现在来看看具体的表设计,如下图:上面 HBase 表的列簇名为c,我们使用人脸id作为列名。我们只使用了 HBase 的一张表就替换了之前方面的三张表!虽然我们启用了 MOB,但是具体插入的方法和正常使用一样,代码片段如下:String CF_DEFAULT = “c”;Put put = new Put(groupId.getBytes());put.addColumn(CF_DEFAULT.getBytes(),faceId1.getBytes(), feature1.getBytes());put.addColumn(CF_DEFAULT.getBytes(),faceId2.getBytes(), feature2.getBytes());……put.addColumn(CF_DEFAULT.getBytes(),faceIdn.getBytes(), featuren.getBytes());table.put(put);用户如果需要根据人脸组id获取所有人脸的数据,可以使用下面方法:Get get = new Get(groupId.getBytes());Result re=table.get(get);这样我们可以拿到某个人脸组id对应的所有人脸数据。如果需要根据人脸组id+人脸id查找某个人脸的具体数据,看可以使用下面方法:Get get = new Get(groupId.getBytes());get.addColumn(CF_DEFAULT.getBytes(), faceId1.getBytes())Result re=table.get(get);经过上面的改造,在2台 HBase worker 节点内存为32GB,核数为8,每个节点挂载四块大小为 250GB 的 SSD 磁盘,并写入 100W 行,每行有1W列,读取一行的时间在100ms-500ms左右。在每行有1000个face的情况下,读取一行的时间基本在20-50ms左右,相比之前的10s提升200500倍。下面是各个方案的对比性能对比情况。使用 Spark 加速数据分析我们已经将人脸特征数据存储在阿里云 HBase 之中,这个只是数据应用的第一步,如何将隐藏在这些数据背后的价值发挥出来?这就得借助于数据分析,在这个场景就需要采用机器学习的方法进行聚类之类的操作。我们可以借助 Spark 对存储于 HBase 之中的数据进行分析,而且 Spark 本身支持机器学习的。但是如果直接采用开源的 Spark 读取 HBase 中的数据,会对 HBase 本身的读写有影响的。针对这些问题,阿里云 HBase 团队对 Spark 进行了相关优化,比如直接读取 HFile、算子下沉等;并且提供全托管的 Spark 产品,通过SQL服务ThriftServer、作业服务LivyServer简化Spark的使用等。目前这套 Spark 的技术栈如下图所示。通过 Spark 服务,我们可以和 HBase 进行很好的整合,将实时流和人脸特征挖掘整合起来,整个架构图如下:我们可以收集各种人脸数据源的实时数据,经过 Spark Streaming 进行简单的 ETL 操作;其次,我们通过 Spark MLib 类库对刚刚试试收集到的数据进行人脸特征挖掘,最后挖掘出来的结果存储到 HBase 之中。最后,用户可以通过访问 HBase 里面已经挖掘好的人脸特征数据进行其他的应用。本文作者:明惠阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 22, 2018 · 1 min · jiezi

TableStore轻松实现轨迹管理与地理围栏

摘要: 基于TableStore轻松实现亿量级轨迹管理与地理围栏一、方案背景轨迹管理系统日常生活中使用非常普遍,如外卖派送轨迹、快递物流流转、车辆定位轨迹等。该场景与地理位置管理类似,核心点与瓶颈都在数据库的存储性能与查询能力,同时需要时间字段正序排列,保证轨迹点顺序;一方面,存储服务需要应对海量数据的低延迟存、读,另一方面,存储服务也要提供高效的多维度数据检索与排序。表格存储(TableStore)对于轨迹管理场景,依然可以胜任,完全具备实现轨迹管理系统的能力。不妨来体验一下基于TableStore打造的【亿量级摩托车管理系统】样例;需求场景某城市市区出于安全考虑,限制摩托车进入一定的区域范围。某摩托车租赁公司,为了更好管理所辖摩托车的违章问题,对自己所辖摩托车安装定位系统,定时采集摩托车位置。摩托车租赁公司,可以通过轨迹管理平台,查询统计违章情况,也可作为依据,提醒违章的租赁用户,过多违章拉入黑名单;查询场景:【2018年11月01日】编号【id00001】的摩托车行驶轨迹与违章情况查询;样例如下:注:该样例提供了【亿量级】轨迹数据。官网控制台地址:项目样例样例内嵌在表格存储控制台中,用户可登录控制台体验系统(若为表格存储的新用户,需要点击开通服务后体验,开通免费,订单数据存储在公共实例中,体验不消耗用户存储、流量、Cu)。表格存储(TableStore)方案采用表格存储(TableStore)轻松搭建一套:亿量级摩托车管理系统。多元索引功能提供GEO检索、多维查询的能力,通过对时间的排序获取追踪设备的轨迹。同时,用户可随时创建索引然后完成自动同步,不用担心存量数据问题。TableStore作为阿里云提供的一款全托管、零运维的分布式NoSql型数据存储服务,具有【海量数据存储】、【热点数据自动分片】、【海量数据多维检索】等功能,有效的地解决了GEO数据量大膨胀这一挑战;SearchIndex功能在保证用户数据高可用的基础上,提供了数据多维度搜索、排序等能力。针对多种场景创建多种索引,实现多种模式的检索。用户可以仅在需要的时候创建、开通索引。由TableStore来保证数据同步的一致性,这极大的降低了用户的方案设计、服务运维、代码开发等工作量。二、搭建准备若您对于基于TableStore实现的【亿量级摩托车管理系统】体验不错,并希望开始自己系统的搭建之旅,只需按照如下步骤便可以着手搭建了:1、开通表格存储通过控制台开通表格存储服务,表格存储即开即用(后付费),采用按量付费方式,已为用户提供足够功能测试的免费额度。表格存储官网控制台、免费额度说明。2、创建实例通过控制台创建表格存储实例,选择支持多元索引的Region。(当前阶段SearchIndex功能尚未商业化,暂时开放北京,上海,杭州和深圳四地,其余地区将逐渐开放)创建实例后,提交工单申请多元索引功能邀测(商业化后默认打开,不使用不收费)。邀测地址:提工单,选择【表格存储】>【产品功能、特性咨询】>【创建工单】,申请内容如下:问题描述:请填写【申请SearchIndex邀测】机密信息:请填写【地域+实例名】,例:上海+myInstanceName3、SDK下载使用具有多元索引(SearchIndex)的SDK,官网地址,暂时java、go、node.js三种SDK增加了新功能java-SDK<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>tablestore</artifactId> <version>4.7.4</version></dependency>go-SDK$ go get github.com/aliyun/aliyun-tablestore-go-sdk4、表设计店铺检索系统样例,仅简易使用一张店铺表,主要包含字段:店铺类型、店铺名称、店铺地理位置、店铺平均评分、人均消费消等。表设计如下:表名:geo_track列名数据类型索引类型字段说明_id(主键列)String MD5(mId + timestamp)避免热点mIdStirng 摩托车编号timestamplongLONG时间点(毫秒时间戳)posStringGEO_POINT车辆位置:“30.132,120.082”(纬度,精度)…………三、开始搭建(核心代码)1、创建数据表用户仅需在完成邀测的实例下创建“摩托车轨迹表”:通过控制台创建、管理数据表(用户也可以通过SDK直接创建):其他表如租赁用户表、摩托车信息表等,根据需求创建:这里仅展示轨迹表,表名:geo_track2、创建数据表索引TableStore自动做全量、增量的索引数据同步:用户可以通过控制台创建索引、管理索引(也可以通过SDK创建索引)3、数据导入插入部分测试数据(控制台样例中插入了1.08亿条(1万辆摩托70天24小时*6个"10分钟点")数据,用户自己可以通过控制台插入少量测试数据);表名:geo_track摩托车编号轨迹点md5(mId + timestamp)(主键)时间店铺位置id00001f50d55bec347253c24dc9144dff3e3b7154110360000030.30094,120.01278表名:moto_user摩托车编号(主键)摩托车颜色摩托车品牌摩托车租赁用户id00001银灰色H牌摩托车杨六4、数据读取数据读取分为两类:主键读取(摩托车信息查询)基于原生表格存储的主键列获取:getRow, getRange, batchGetRow等。主键读取用于索引(自动)反查,用户也可以提供主键(摩托车编号)单条查询的页面,查询速度极快。单主键查询方式不支持多维度检索;索引读取(轨迹信息查询)基于新SearchIndex功能Query:search接口。用户可以自由设计索引字段的多维度条件组合查询。通过设置选择不同的查询参数,构建不同的查询条件、不同排序方式;目前支持:精确查询、范围查询、前缀查询、匹配查询、通配符查询、短语匹配查询、分词字符串查询,并通过布尔与、或组合。如【2018年11月01日,id00001号摩托车,行驶轨迹及违章查询】Query条件如下:List<Query> mustQueries = new ArrayList<Query>();List<String> polygonList = Arrays.asList(//地理围栏,禁摩区域 “30.262348,120.092127”, “30.311668,120.079761”, “30.332413,120.129371”, …);String mId = “id00001”;Long timeStart = [2018-11-01时间戳];Long timeEnd = [2018-11-02时间戳];GeoPolygonQuery geoPolygonQuery = new GeoPolygonQuery();geoPolygonQuery.setPoints(polygonList);geoPolygonQuery.setFieldName(“pos”);mustQueries.add(geoPolygonQuery);TermQuery termQuery = new TermQuery();termQuery.setFieldName(“mId”);termQuery.setTerm(ColumnValue.fromString(request.getmId()));mustQueries.add(termQuery);RangeQuery rangeQuery = new RangeQuery();rangeQuery.setFieldName(“timestamp”);rangeQuery.setFrom(ColumnValue.fromDouble(timeStart, true);rangeQuery.setTo(ColumnValue.fromDouble(timeEnd, false);mustQueries.add(rangeQuery);BoolQuery boolQuery = new BoolQuery();boolQuery.setMustQueries(mustQueries);这样,系统的核心代码已经完成,基于表格存储搭亿量级“摩托车管理系统”,是不是很简单?本文作者:潭潭阅读原文本文为云栖社区原创内容,未经允许不得转载。

November 15, 2018 · 1 min · jiezi

Centos7 防火墙 firewalld 实用操作

一.前言Centos7以上的发行版都试自带了firewalld防火墙的,firewalld去带了iptables防火墙。其原因是iptables的防火墙策略是交由内核层面的netfilter网络过滤器来处理的,而firewalld则是交由内核层面的nftables包过滤框架来处理。 相较于iptables防火墙而言,firewalld支持动态更新技术并加入了区域(zone)的概念。简单来说,区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以根据生产场景的不同而选择合适的策略集合,从而实现防火墙策略之间的快速切换。区域对于 firewalld 来说是一大特色,但是对于我们使用Centos7一般是在服务器上,需要切换zone的需求比较少,所以本文不做介绍了,网上资料也比较多,大家可以去百度找找资料。二.操作与配置1.服务操作启动服务:systemctl start firewalld这里不用担心启用了防火墙以后无法通过ssh远程,22端口默认加入了允许规则停止服务:systemctl stop firewalld重启服务:systemctl restart firewalld查看服务状态:systemctl status firewalld2.配置文件说明firewalld 存放配置文件有两个目录,/usr/lib/firewalld 和 /etc/firewalld,前者存放了一些默认的文件,后者主要是存放用户自定义的数据,所以我们添加的service或者rule都在后者下面进行。server 文件夹存储服务数据,就是一组定义好的规则。zones 存储区域规则firewalld.conf 默认配置文件,可以设置默认使用的区域,默认区域为 public,对应 zones目录下的 public.xml三.命令这里需要首先说明的是,在执行命令时,如果没有带 –permanent 参数表示配置立即生效,但是不会对该配置进行存储,相当于重启服务器就会丢失。如果带上则会将配置存储到配置文件,,但是这种仅仅是将配置存储到文件,却并不会实时生效,需要执行 firewall-cmd –reload 命令重载配置才会生效。1.重载防火墙配置firewall-cmd –reload2.查看防火墙运行状态firewall-cmd –state3.查看默认区域的设置firewall-cmd –list-all4.应急命令firewall-cmd –panic-on # 拒绝所有流量,远程连接会立即断开,只有本地能登陆firewall-cmd –panic-off # 取消应急模式,但需要重启firewalld后才可以远程sshfirewall-cmd –query-panic # 查看是否为应急模式5.服务firewall-cmd –add-service=<service name> #添加服务firewall-cmd –remove-service=<service name> #移除服务6.端口firewall-cmd –add-port=<port>/<protocol> #添加端口/协议(TCP/UDP)firewall-cmd –remove-port=<port>/<protocol> #移除端口/协议(TCP/UDP)firewall-cmd –list-ports #查看开放的端口7.协议firewall-cmd –add-protocol=<protocol> # 允许协议 (例:icmp,即允许ping)firewall-cmd –remove-protocol=<protocol> # 取消协议firewall-cmd –list-protocols # 查看允许的协议8.允许指定ip的所有流量firewall-cmd –add-rich-rule=“rule family=“ipv4” source address="<ip>” accept"例:firewall-cmd –add-rich-rule=“rule family=“ipv4” source address=“192.168.2.1” accept” # 表示允许来自192.168.2.1的所有流量9.允许指定ip的指定协议firewall-cmd –add-rich-rule=“rule family=“ipv4” source address="<ip>” protocol value="<protocol>" accept"例:firewall-cmd –add-rich-rule=“rule family=“ipv4” source address=“192.168.2.208” protocol value=“icmp” accept” # 允许192.168.2.208主机的icmp协议,即允许192.168.2.208主机ping10.允许指定ip访问指定服务firewall-cmd –add-rich-rule=“rule family=“ipv4” source address="<ip>” service name="<service name>" accept"例:firewall-cmd –add-rich-rule=“rule family=“ipv4” source address=“192.168.2.208” service name=“ssh” accept” # 允许192.168.2.208主机访问ssh服务11.允许指定ip访问指定端口firewall-cmd –add-rich-rule=“rule family=“ipv4” source address="<ip>” port protocol="<port protocol>" port="<port>" accept"例:firewall-cmd –add-rich-rule=“rule family=“ipv4” source address=“192.168.2.1” port protocol=“tcp” port=“22” accept” # 允许192.168.2.1主机访问22端口12.将指定ip改为网段8-11 的各个命令都支持 source address 设置为网段,即这个网段的ip都是适配这个规则:例如:firewall-cmd –zone=drop –add-rich-rule=“rule family=“ipv4” source address=“192.168.2.0/24” port protocol=“tcp” port=“22” accept"表示允许192.168.2.0/24网段的主机访问22端口 。13.禁止指定ip/网段8-12 各个命令中,将 accept 设置为 reject 表示拒绝,设置为 drop表示直接丢弃(会返回timeout连接超时)例如:firewall-cmd –zone=drop –add-rich-rule=“rule family=“ipv4” source address=“192.168.2.0/24” port protocol=“tcp” port=“22” reject"表示禁止192.168.2.0/24网段的主机访问22端口 。四.参考资料firewalld防火墙详解 by xuad88.本文作者:晓晨master阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 13, 2018 · 1 min · jiezi