首页 文章 精选 留言 我的

精选列表

搜索[趋势探讨],共10000篇文章
优秀的个人博客,低调大师

探讨:赢了围棋后,人工智能离看病还有多远?

谷歌AlphaGo和李世石进行了围棋人机大战之后,人工智能开始变得炙手可热。据CBinsights统计,2015年共有397起投资事件,23.88亿美元被投入到人工智能领域,与2011年相比投资额增长了近9倍。 为了扶持人工智能的发展,国家也发布了《互联网+人工智能三年的行动实施方案》,期望能在2018年打造人工智能基础资源与创新平台,人工智能产业体系、创新服务体系、标准化体系基本建立。 在医疗领域,IBM推出Watson Health(沃森健康)。它能应用在癌症的诊疗上,通过对医学影像的分析和学习,帮助MD安德森医院的医生做出对癌症患者的精准诊断。 至此,我们不禁想进一步释疑:人工智能在医疗领域究竟能做哪些?前景如何?在实际应用场景中,哪个场景能率先获得突破?大医疗大健康延展来看,在智能陪护和养老等领域,人工智能会有哪些价值? 为此,云

优秀的个人博客,低调大师

工业视觉云边协同:网络传输瓶颈与技术选型探讨

工业视觉正从"单机识别"走向"云边协同"。随着5G工厂和工业视觉应用持续落地,越来越多企业采用边缘推理与云端训练结合的架构——轻量推理部署在工厂边缘,复杂训练任务上移至云端GPU集群。但网络逐渐成为瓶颈:大体积图像回传能否满足业务时延要求?批量样本是否会挤占产线带宽?工厂断网后质检是否停摆?

优秀的个人博客,低调大师

低代码平台探讨-MetaStore元数据缓存 | 京东云技术团队

背景及需求 之前提到我们模型驱动的实现选择的是解释型,需要模型的元数据信息,在接到请求后动态处理逻辑. 此外,应用的通用能力中还包括:页面dsl查询,菜单查询等. 而且后期加入触发器,用户自定义api后,这些元数据也需要提供查询服务. 所以我们需要一个元数据模块,需要提供两个基础功能:加载元数据和提供元数据查询服务.  特殊说明:最开始的时候我们支持两种源:本地和远程,后期防止单独部署网络隔离问题把远程逻辑去掉了. 第一版迭代处理的元数据有:模型,页面dsl及菜单,后期加入触发器,用户自定义api,拦截器等,我们今天按照第一版迭代来讨论设计及实现. 模型元数据的需求是缓存一批模型元数据,可以根据模型name获取模型的具体信息. 页面dsl的需求是缓存一批页面dsl,根据dslId获取页面dsl信息. 菜单的需求比较简单,缓存菜单列表和获取菜单列表. 上边说的是功能性需求,接着说下非功能性需求: 性能,元数据的查询特别频繁,必须保证高性能,通常会使用缓存,这也是我们这个模块的核心价值之一. 数据要准确,从MetaStore获取的数据不能有问题和差异. 易于扩展,首先元数据不仅仅有根据id获取的需求,可能还有其他查询需求;其次后期加入其他元数据存储的时候要改动小. 初版设计 设计思路 上边说了需求,下边我们开始正式的设计,先选一个具体场景来说:模型元数据. 为了高性能肯定要使用缓存,开发中常用缓存方式有两种:远程和本地. 远程通常使用NoSql的中间件,如Redis和MemCache,在这种场景下肯定不适合. 该场景最适合的方式是使用内存缓存,查询逻辑简单:根据name或者id获取,所以直接使用map的数据结构即可. 元数据是在应用启动时加载,不会再有变动(后期热部署此处需要重构),利用spring的启动机制,也不用考虑线程安全问题,直接使用HashMap就可以,这里应该是利用的jvm的Happens-before原则. 到此,我们确定了缓存的数据结构及接口:  包含一个内部变量cache是HashMAP类型,一个内部方法去加载数据,对外一个接口方法getByKey,功能比较内聚,类设计是没问题的,下边我们看下具体的逻辑. 详细逻辑 getByKey的逻辑是从缓存变量cache中获取,直接使用map的get方法,不用赘述(此处有坑,下文会有说明),主要看下load加载数据的方法  主要逻辑: 1. 读取指定的目录,可以从配置中获取,获取不到使用默认值:models,读取出目录下所有文件. 2. 开始循环处理每个文件,详细步骤: 1. 读取出文件内容:json格式. 2. json数据转换成Model对象. 3. 把Model对象放入到cache中,key是modelName,value是Model对象. 抽象 当具体方案确定后,如上边所述的逻辑实现起来并不复杂,甚至可以说是简单. 但我们在整体看下会发现:模型和页面dsl的元数据缓存逻辑相似度特别高! 再回头看下上边的逻辑流程图,紫色的部分都是完全相同的,差异只存在与红色的两块逻辑:"读取指定目录"和"解析成对象",我们可以把公共的逻辑抽象出去,做成抽象的父类让子类去继承,利用了继承的代码复用的场景,这是一个典型的模板模式的应用场景. 简单说下模板模式的定义:在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现,让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤. 结合我们的场景来说下:算法骨架就是整体的加载数据流程和获取元数据方法,子类(ModelMetaStore和PageMetaModel)需要实现骨架中的两个扩展方法:"读取指定目录"和"解析成对象". 第一版设计重构后,类图如下  说明: 模型数据文件和页面dsl文件都放到各自的目录:models和dsls下,上边两个目录是默认的,但可自定义配置. 模型数据目录下的文件类型都是json,文件名是模型名称. 页面dsl目录下的文件类型也都是json,文件名是page的id. 抽象出一个父类AbstractDataStore<R>,泛型是子类的对象类型,包含核心逻辑和骨架.内部有一个map类型的cache变量和一个load私有函数用于加载数据,此外提供了两个抽象方法,一个是directoryName:获取文件所在目录,另一个方式是parse:根据文件内容解析成单个对象,这两个抽象方法需要子类实现,最后还有一个根据key获取元数据的公共方法. ModelMetaStore和PageDataStore继承了父类AbstractDataStore,泛型分别是ModelEntity和PageEntity,实现上述的两个抽象方法:directoryName和parse,两个方法的逻辑都特别简单,第一个直接返回自己的目录,第二个利用fastjson把字符串解析成指定对象. 组合 上面把模型和页面的元数据缓存设计完成了,还有一个菜单的元数据缓存. 菜单的元数据结构与上边的两个差异很大,每个应用中只会有一个菜单的元数据文件,所以无法使用上边的模板模式,我们需要单独去处理它的逻辑. 实际上菜单的元数据加载逻辑和其他两个(更准确的说应该是抽象类)有一部分重叠:读取文件的内容,这里面需要判断文件是否为空,读取内容字符串及io读取报错等. 这部分逻辑可以复制出来放到菜单的元数据缓存类中,但实际违背了DRY 原则:不要写重复的代码. 那么该如何解决这块重复代码的问题呢?有两个方案: 第一个方案:使用继承. 在AbstractDataStore<R>上再加一层抽象类,里面只包括一个方法:读取文件内容,新的菜单元数据缓存也继承这个抽象类,把读取文件内容的方法移到最上层,类结构图如下: 这个方案有两个问题: 继承层次太深,逻辑有点乱 最上层的抽象类很难起名 AbstractDataStore和MenuDataCache继承LoadFileData从代码上是可行的,但逻辑上不太合理,抽象继承是is-a的关系,这里需要给LoadFileData一个合适的名字才满足设计规范,而这个名字并不太好起. 第一个方案:使用组合. 这个方案实际上更合理一些,面向对象设计有一个原则:组合优于继承. 可以把读取文件内容的逻辑独立出去作为一个新的帮助类DataLoadSupport,AbstractDataStore和MenuDataCache引入它就可以解决代码重复问题.   初始化加载 上一步几乎完成了所有逻辑,但是少了数据加载的触发,这个需要放到服务启动的时候触发. 我们利用了spring的ApplicationListener,有一个细节问题要确定:如何实现ApplicationListener,是每一个类中单独实现,还是统一实现. 为了逻辑的统一,还有后期其他服务需要启动时加载的考虑,我选择了统一实现,具体逻辑和类图如下: 具体逻辑: 新增一个接口StartLoadListener:启动加载监听,启动时需要被触发的操作类实现该接口. AbstractDataStore和MenuDataCache实现StartLoadListener接口,标记需要在应用启动时触发,应用启动后触发自己的load方法. 新增StartLoadListenerManager类,里面会自动注入所有实现StartLoadListener接口的对象,该类同时实现了spring的ApplicationListener接口,在spring启动后被触发,触发后调用所有的StartLoadListener的startLoad方法,完成所有需要启动时触发的操作. 类图:  第二版设计 如文章开头所说,从元数据缓存中使用key从map中获取信息后直接返回是有问题的,开发完的时候也意识到了一些,但没有去处理,直到某天雷真的炸了. 先说下问题出现的过程,初期功能简单,低代码平台生成的应用都跑的好好的,迭代数次版本后,新增了权限能力:支持简单的数据权限和菜单权限. 菜单权限的处理逻辑大体如下: 从菜单缓存中直接获取缓存的数据. 如果菜单列表为空,直接返回给客户端空的列表,结束菜单查询. 查询用户有权限的菜单编码列表(set),数据源头是科技权限系统,初期比较粗暴代码耦合到菜单权限代码中,但这不是今天讨论的重点,后边的文章会讲到权限模块的重构. 如果用户有权限的菜单编码列表(set)为空,直接返回给客户端空的列表,结束菜单查询. 递归处理获取的缓存菜单,如果编码在权限系统返回的编码列表(set)中,递归处理子节点列表(菜单是树形的),否则直接删除该节点,返回到上级递归. 循环上步操作,直到所有菜单节点校验完成.   逻辑并不太复杂,开发的时候特意重点关注了递归和权限系统查询,本地测试没什么问题,部署到测试环境也没发现什么问题. 但最后要上线前测试发现了一个问题:切换账号后,菜单不对,有权限的菜单变少了!!! 定位问题的时候,先排查权限系统的返回,结果没问题;在把数据拿到本地走mock测试也没有问题;在最后debug的时候发现了真正的问题,也就是之前意识到但没有解决的问题:在菜单权限逻辑中操作的菜单列表和菜单元数据缓存的菜单列表是同一个对象! 在某个用户处理完自己的权限菜单逻辑后,可能会移除一些节点,下一个用户在获取菜单的时候他的菜单元数据可能就是被处理过(在权限处理中被移除)的了. 元数据存储实际上类似原型模型,原型模式的定义:如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的. 我的实现只做了缓存,但没有实现复制,使得同一对象被多个场景操作.最后导致数据的错误及混乱. 而复制一般也叫拷贝,分为两类: 浅拷贝:只会拷贝对象中的基本数据类型的数据(比如,int、long),以及引用对象的内存地址,不会递归地拷贝引用对象本身. 深拷贝:不仅仅会复制索引,还会复制数据本身 我们肯定要选择深拷贝,但出现问题的时候已经有几个元数据存储了,特别是菜单数据的结构复杂(树形),短时间没法完成深度复制,市面上的工具类通常只能复制一层,无法自动完成深层次的复制. 当时的解决方案比较粗暴:问题出现在菜单,那只在菜单权限处理的时候做手脚:定义一个新的菜单列表,有权限的菜单深度复制当前对象后加入到list;递归处理子节点.继续重新定义一个list设置为上层节点的子节点,有权限的子节点放入到新的list,递归循环上述步骤. 表象的bug解决了,但实际问题还没有解决,只是被遮盖了,就拿菜单来说,我是在权限服务那处理了,但如果在其他地方使用呢,一样会出现数据缺失的错误. 更严重的是在触发器中提供了获取模型元数据的接口,开发者获取模型元数据后如果进行了修改,导致的错误会更加严重,也更加的难已排查,因为模型元数据的变更会导致模型通用接口逻辑的缺失或混乱,所以深度复制的功能一定要实现. 深度复制的实现一般有两种: 第一种序列化后反序列化,比如把数据序列化成json,在反序列化回来.该方案有两个问题:(1)继承的子类多态容易出问题(2)序列化和反序列化是有性能消耗的,在此处方案并不适合. 第二种是递归处理:遇到Collection和Map及javabean类型,进行递归的深度拷贝.该方案开发成本稍高,大量的递归需要特殊注意,此外一些特殊的bean也无法复制:如内部变量是final类型,或者只支持构造函数传入. 我们使用的是第二种,这种方法纯粹是算法类,不再细说,在中间碰到了一个坑:我有一个习惯遇到一些没有数据需要返回空的list的时候我会直接使用Collections.emptyList(),在深度复制的时候根据构造函数新建对象会直接报错,修复方案是:如果是list或者map不是常见的对象类型直接使用常见的对象ArrayList和HashMap.  实际上还有一种方案能解决数据修改问题,使用不变对象,不变对象就是对象在创建后,不可以被修改:没有set方法,且内部变量不会暴露,需要注意的是,内部变量也要进行保护:不变或者深拷贝. 作者:京东科技吴籽良 来源:京东云开发者社区 转载请注明来源

优秀的个人博客,低调大师

面向未来的开源 OLAP 技术架构探讨以及选型实践

摘要:本文将介绍开源大数据 OLAP 的演化过程和最佳实践。文章将围绕下面六点展开: 1.开源 OLAP 综述 2.OLAP 场景思考 3.开源数据湖/流式数仓解决方案 4.StarRocks 介绍 5.客户案例 6.未来规划 一、开源 OLAP 综述 基于历史发展和开源社区的火热,现在的OLAP技术可以用百花齐放四个字来形容。 如图中最左边这一部分,是现在比较流行或者已经是业界标准的 OLAP 数据仓库/LakeHouse,包括 StarRocks、Doris、ClickHouse。第二部分是 SQL on Hadoop,该技术于10年前开始,以 HDFS 平台或者 OSS 为存储底座,包括 Presto 以及分支出来的 Trino、Impala。第三部分是预处理/Cube/NoSQL,已经使用得越来越少,麒麟、Druid 社区以及背后的商业化公司活跃度不高,Hbase 目前主要用在 Serving 的场景,社区相对比较老,稳定性尚可,解决了一部分业务场景,应用规模不小,但热度在逐渐下降。第四列是离线部分,目前的事实标准是 Spark,比较老的技术栈则是 Hive。 最底下这一部分是数据湖格式,之所以放在最下面,是有原因的。Delta Lake 在2019 年推出了增量数据湖格式,后期包括 Hudi,Iceberg,被大家称作数据湖三剑客。它们主要解决数据增量更新的问题。在大多情况下,作为 Presto、StarRocks 的外表,以读的方式作为 OLAP 来使用。Apache Paimon 是 Flink 社区推出的,原来叫 Flink Table Store,目前也贡献到了 Apache 社区,以 Flink 为基础,把整个存储留在湖里。 二、OLAP 场景思考 典型业务场景 OLAP 的业务场景主要有四大类: 第一类是面向用户的报表,比如一个比较典型的场景,给第三方广告主出报表,它可能是一个 ToB 的公司,利用 OLAP 引擎去做 Serving 服务; 第二类是面向经营人员、数据分析人员、老板的一些经营的报表,也是传统 BI 的 OLAP 行为; 第三类是用户画像,在游戏等行业里用得非常多,主要是把所有的用户标签统一到一张比较宽的表里,可以用各个维度去筛选出需要的客户; 第四类是流式的、实时的场景,包括直播、风控、实时预测。 接下来将介绍这几种业务场景对 OLAP 技术的需求及解决方案。 面向客户的报表 面向客户的报表,业务特点是按照客户的ID去检索数据,需要低延迟、高并发,而且需要明细数据,不仅仅是聚合模型。基于明细可以实现更灵活的自助分析,或者称作实时OLAP。但是实时 OLAP 性能也会受限制,比如三张表、十张表的 Join 查询的 latency 可能会非常的高,所以我们需要去做物化视图。总结起来,业务场景的需求是明细加上物化视图。 在技术上的需求,第一点是数据过滤,比如前缀索引、Bloom filter,以及一些更高级的filter,通过一些统计值有效过滤,减少读取的数据,使得点查或者范围查询更加快速。 第二点是向量化引擎,Presto、Hive、Spark 在某一个时间点上都有 OLAP 的尝试。当然现在 Presto、Trino 社区还是非常活跃的,尤其是在国外,它们是通过 Java 技术栈实现的,但是 Java 技术栈从语言层面而言没有 C++ 快,同时因为JVM向量化现在还不是特别成熟,也不能利用JVM的向量化模式。当然 Trino 社区在不断地去做这件事,不过到现在还没有一个完整的产品。另外 Presto,也在做 Native 的 Engine,去解决 OLAP 加上向量化的问题。但是有一些数据库,包括 ClickHouse、StarRocks、Doris,在几年前就已经布局了向量化引擎,因为其整个执行引擎本来就是用C++写的,所以会更快。 第三点是数据在机器的合理分布,数据分布对查询影响也是比较大的,包括数据是否有序、是否是 shard。 最后一点是对物化视图的支持是否足够好。 面向经营的报表 面向经营的报表,一般是企业内部提供给老板和数据分析人员查看的报表,比较典型的是实时风控场景。业务特点首先是需求变化特别快,要有明细表的存在,不只聚合成一种预设的模式,一般要把明细表直接导入到数据仓库中。第二是要求响应低延迟,对查询性能要求很高。 低延时对技术的需求包括向量化极速查询、多表关联查询能力、物化视图等等。 ClickHouse 针对宽表的场景,把整个数据通过 shard 分布,每一台机器进行分布式计算,最后将结果汇总起来形成查询的结果。ClickHouse 宽表比较快,但是宽表维护起来比较麻烦。所以我们思索是否有一种引擎可以对明细模型做高效的分布式 Join,在具有多机多核的同时也有核的向量化。 用户画像 用户画像场景是以一个ID为主键,构成一张列特别多的宽表。在 StarRocks 出现之前,更多用的是 Flink 或者 Spark 在外围加工出一张可能上千列的宽表,再直接 load 到数据库中,比较常见的是 ClickHouse 中。现在由于 StarRocks 逐渐崛起,很多需求都落到了 StarRocks 上。因为多表关联的能力也是需要的,如果用户画像只用宽表来做,还是有一些限制。在跟客户交流的过程中了解到,ClickHouse 这条链路会存在烟囱式开发的问题,维护起来有难度,所以 ClickHouse 的高效是牺牲了一定的运维能力。另外ClickHouse 对人员的要求也比较高,因为业务线的人员更多的是关注业务,这时要求业务线的人员去对 ClickHouse 进行维护就会存在困难。 订单分析 订单分析场景,在没有增量数据湖格式出现之前,用 Hive 或 Spark 一般是T+1的形式,如果要进一步提高时效,可能会用更短的时间去建分区,比如一个小时一个分区,但如果对这类分区表做全量刷新则会非常不友好,无论是对数据湖还是调度,压力都非常大。现在希望实时或者准实时地去分析数据,增量数据湖,包括 Delta Lake、Hudi、Iceberg 就是为了解决这一问题。 在线教育、企业订单、打车软件等场景,常常需要数据回刷,这对数据湖来说是一个非常大的挑战。在有了更新模型之后,很多企业开始把整个链路加到 Hudi,或者 Delta Lake上面。比如上一次的数据是一个小时之前的数据,下一个小时去更新这一批数据,但是如果做 OLAP 查询,速度会比较慢。因为直接查湖上的数据,受网络 IO 影响比较大。另外数据湖后台的 Compaction 要求比较高,尤其流量特别大的时候,很难同时保证数据查询的新鲜度和查询性能的要求。 StarRocks 引出了一部分主键模型,能够直接把 MySQL 或者原始数据直接打到主键模型里,通过主键的方式去更新,同一个主键,实现部分列的更新,是一种最佳实践。 技术需求思考 通过上述场景分析,对技术需求可以总结为如下几大类: 多表关联 首先是对 SQL 的支持,比如是否支持 IC SQL,还是会违背 IC SQL的语法,有很多自己的 SQL 语法。引申就是有没有一些 MySQL 协议或者是 PG 协议,直接可以去对接更好的BI工具,能够较少地去改动。 其次是对 Join 的支持。对比 StarRocks 和 CK,可以看出来,StarRocks 对于分布式 Join 的支持是特别好的,因为它有 FE 去做整个的 CBO,比如有5张表去做 Join a,Join b,Join c,Join d、 Join e 以怎样的顺序去做 Join,这时就需要通过 CBO 算法来挑出一个最好的方式。 另外是分布式 Join 的支持。StarRocks 还有一些其它的特性,通过数据的分布,实现一些 Join 的高级特性,比如 broadcast Join、shuffle Join,对比起来 CK 这几点就比较弱,因为 CK 最开始的时候是类似于以单机的形式拓展的分布式,它不是 MPP 架构,而是 Scatter-Gather 的架构。Scatter-Gather 架构需要去手动地把整个数据分成不同的Shard,每一台机器计算自己的 Shard,再把整个数据回吐到一个中心节点,这样就相当于是两层架构,对于 Join 的支持是很有限的。 多维查询 需要关注性能和索引的支持是否完备,以及一些高级的特性比如物化视图。物化视图在 StarRocks 里是一种比较重要的特性,包括同步物化视图、异步物化视图、单表物化视图、多表物化视图等。 实时导入和查询 是否有 Exactly Once 的语法保证。StarRocks 是能够保证的。CK 也是支持事务的,但分布式事务存在一些缺陷。是否有 Update 功能,包括 Partial Update。Schema Change 的感知。列数的限制,宽表限制了1000列还是1万列是有本质区别的。 开发效率、架构和运维 对于企业,开发效率、架构、运维难度可能更加重要,很多情况下企业人员并不是那么充足,运维的简便就很重要,比如能否以最小代价弹性缩容,能否根据扩缩容来自动均衡,是否能够达到高可用等等,都是非常实际的问题。开发效率方面,比如函数的支持是否完备,UDF 支持是否完备。现在越来越多的客户也都是湖仓的架构,本身有一些湖数据,这些数据是否可以不导进来,可以直接查询,也是一个特别常见的刚需。 三、开源数据湖/流式数仓解决方案 整体架构 上图是EMR的整体架构。以 ECS 或 Kubernetes 作为底座,主推方向是存算分离。左边是 JindoFS 加上 OSS,我们叫做 HCFS, Hadoop Compatible FS。Spark、Presto 这些计算引擎,不需要更改任何接口,直接能够对接以 OSS 为底座的 HCFS。其中有一些引擎是比较活跃的,也有一些基本上已经退出了历史舞台。 上面是一些数据分析或者数据应用平台的组件,下面将介绍的是企业架构。 Lambda 架构 第一个是 Lambda 架构,是最传统的一套架构,也是大厂现在用得最多的。离线和实时分别走不同的链路。图中这一块分层 ODS、DWD、DWS,放在 OLAP 的数据仓库里,这一层直接体现了报表的查询响应速度,可以用类似 Presto、Trino 这类引擎去查询,这是比较传统的架构,这里最终加工出来的最后一层的报表,直接放在 OLAP 里。 实时数据湖解决方案 第二个是相对比较新的一种架构,它提供了按主键 merger into 的能力,解决增量更新的场景。 这套架构计算会比较频繁,原来只是T+1,现在则需要实时或者近实时,比如半小时,几分钟去做更新,逐渐向流批一体靠拢。因为Iceberg、Hudi两个数据湖格式对批引擎和流引擎是完全适用的,这点在选型时大家也会着重考虑。对于查询数据湖,有越来越多的客户,从 Trino 或者 Presto 迁移到 StarRocks 上,因为目前 StarRocks 对于 Data Lake Analytics(DLA),也就是读外表的数据,支持是非常好的。 大家如果关注 StarRocks 社区版3.0会了解到,除了 UDF,StarRocks 能够提供和 Presto一模一样的语法,叫做 Presto Gateway,可以在不改 Presto 的 SQL 的情况下,就能够查询湖数据。这个能力将会包含在EMR 2.5的版本上。 最开始我们是最后一层 ADS 导入到 OLAP 中,现在有很多客户是希望 ODS、DWD、DWS 里面挑选一些比较关键的表,提供比较高的性能,也导入到 OLAP 中,然后通过 OLAP 完成高效的查询。 实时分析解决方案 上图是传统的 Kappa 架构,对于一些垂直业务线部门,不是数据中台部门,需要做这样一套数仓来解决其业务问题。通常是用 Flink CDC 把 MySQL 的数据同步到 Kafka 里,数据一般存储7天或者3天。虽然商业版的 Kafka 可以提供 KSQL,但在 Kafka 里查询数据,性能一直都是不太好的。 所以通常把整个 Kafka 数据通过 routine load 直接导到数据仓库里面,或者直接导到StarRocks 里面,这样就能保证 ODS、DWD、DWS 这三层数据全部可以增量查到,也能够去做整个的 OLAP,ODS 和 DWD 这两层的表也可以去做一些 Join。 StarRocks 的物化视图会在2. 5版本或者之后的几个小版本才能够比较稳定地跑起来,现在提供的是类似于全量物化视图,或是分区物化视图,而不是那种完全的 Incremental 物化视图。另外2. 5版本有外表物化视图,也可以把一些比较重的表,或者是我们通常叫做大湖小仓,把所有的数据放到湖里,需要的数据导到仓里。导入到仓里的时候也提供了一种比较暖心的方式,会去做外表的优化视图进行数据的导入。比如按时间,每10分钟导一次,把外表物化视图直接导进 StarRocks 里边,而不是用灌数据的方式。直接通过物化视图的方式,内部也会起更多的物化视图,也会在物化视图里边去建物化视图,这样把每一层的数据全部都物化起来,这也是 StarRocks 社区版中主推的。 四、StarRocks 介绍 接下来介绍 StarRocks 的价值和一些关键技术。 StarRocks 价值&架构 StarRocks 主打极速统一的概念,3. 0也会主打云原生这一概念。统一方面,StarRocks可以进行多维分析、实时分析,包括高并发查询、AD hoc 查询,包括前面介绍的所有场景,希望能够都统一起来,逐步在演化过程中,也慢慢地都开始做到了。在极速方面,StarRocks 对特别多的细节优化得也相当到位。通过 StarRocks 可以解决目前的大部分问题。 StarRocks 架构简单。FE 如果是高可用,则是有三个节点,它是通过 BDB 的库去做journal log 同步,类似于 raft 协议。BE 包括执行引擎和 IO 的引擎。比如查数据湖时,数据不在本地,所以整个 BE 节点,没必要去启动存储引擎,只需要计算引擎就可以。 StarRocks 核心技术特性 上图中列出了向量化的优化效果(2.1版本)。对于几个算子,比如 filter、group、shuffle Join、broadcast Join 等算子的性能提升是比较明显的。只要查询是非常重计算,轻 IO 的,最后整个查询的性能提升会非常明显。 StarRocks CBO 优化器采用 Cascades 框架。其中 Join 的推算是用动态规划算法实现的。 分布式 Join 的能力包括 Shuffle Join、Bucket Join、Colocation Join 等。Colocation Join 是指不需要网络传输,事先把两张表的数据,需要被 Join 的 key 置于同一台机器上,可以不走网络,不走 shuffle 的过程,这样能够显著加速 Join 的过程。但这种方式使用起来还是有一些门槛的,实际中不仅需要非常懂业务,还需要懂 Colocation Join 命中的规则,才能将其真正用起来。但是一般情况下 Shuffle Join,Bucket Join,Broadcast Join 也都够用了。 实时分析方面,StarRocks 有一个比较重要的特性——主键模型,也是不断地在优化中。1. 9的版本开始出现主键模型,一直优化到2. 5版本,经历了一年多,所以稳定性、内存的使用、以及 Partial Update 这些方面都表现优异。 整体性能方面,如果是查询数据湖外表,采用 TPCH 的标准跟 Trino 对比是3- 5倍的差距,数据来源 StarRocks 官网,或者是阿里云EMR官网。如果是在自己的业务,自己的 SQL 上,可能会有差异,但是有好有坏,如果查询是IO瓶颈的,那无论计算还是索引优化得多么好,也不一定有多大的提升,瓶颈卡在IO上,StarRocks 的向量化计算,包括一些高级的索引都没用上。但IO用的不是特别多,主要都是在函数计算,或其它方面,算子运行时间长,那么提升可能会非常多。 SSB 100G对比的是单表场景,数据来源 ClickBench 网站。在 CK 的优势领域,单表查询上,StarRocks 目前表现也是比较突出。如果感兴趣可以访问 ClickBench 官网。 StarRocks 目前也有资源隔离能力,如果要自建 StarRocks,资源隔离能力用得是比较多的。如果是在阿里云的场景上,或者后续要推出存算分离的场景,资源隔离能力,可以去官网上参考,但是在我们的客户里边用的并不是特别多。 最后是副本自动平衡的能力。如果去扩一台机器或者缩一台机器,不需要去手动做副本平衡,或者一台机器坏了,或者一个副本坏了,都是由 FE 的 task 去做平衡。 五、客户案例 某社交领域客户 第一个案例是某社交领域客户,他们最开始用的是CK。在StarRocks 2. 1时,他们开始用 StarRocks 去做整个的关联查询,用CK去做宽表的查询。但后来他们不愿意去维护两个技术栈,所以就去掉了CK,目前基本上用 StarRocks 支撑了所有的业务,包括用户画像、点查,以及传统的 OLAP 多表关联查询。 某电商领域客户 第二个案例是一个电商领域的客户,它们有着非常强烈的统一 OLAP 的需求。之前他们的 OLAP 由于历史原因用得特别乱,运维人员又比较少,维护困难。最后统一到了 StarRocks 里。首先,他们看中了阿里云的专家支持能力;同时,也看中了社区的发展,在社区中提出的问题总能得到较快的回答;另外,StarRocks 基本满足了他们所有的需求。 某在线教育客户 在线教育这个案例中,之前是通过 Hive 做小时级的更新,也无法实现 Upsert 场景,后面迁移到了 Hudi 数据湖上,中间链路除了 Flink 也使用了 Spark。属于大湖小仓,他们把一些关键的、性能要求高的数据都导到 StarRocks 里,对性能要求不那么高的就通过外表的方式直接查询 Hudi。经过数月的生产实践,目前已非常稳定。 六、未来规划 StarRocks3.x:极速统一&云原生 最后来介绍一下 StarRocks 3.x 版本的规划。 包括几条线,第一,继续坚持极速统一这一特性;第二,积极配合去做云原生,存算分离。 大家可能会有一个比较大的困惑,如果用 StarRocks 做仓,那么我们提供的都是云盘,毕竟从成本上来看是要比 OSS 贵不少。所以是否能够类似于 Snowflake,把整个数据全部放到 OSS 里边,只是把云盘作为缓存层去做。 在 LakeHouse 这一部分,2. 3的版本外表查询已经比较完备了,但是对于 Iceberg、 Hudi 的支持,还有很多工作要做。因为StarRocks社区是全球化的,在海外客户对于 Iceberg 用的还是比较多的。 在 ETL 方面和 Snowflake 对标,从3. 0 StarRocks 已经不是纯内存去做ETL了,会有 spill 框架。如果做一个比较大的 ETL 可以 Spill,有限的内存就可以把数据算好。比如做 Hashmap,Hashmap就可以去不断地往磁盘里面去写,有Spill的框架去支撑整个算子。 做ETL的时候并不像 Spark 那样 stage by stage,把每一个 stage 数据都存下来,保证容错性。思路是做得足够快,比Spark快上几倍,即使中间有问题,直接可以通过重算 Job来解决。 但是 ETL 也有资源隔离的问题。资源硬隔离,指的不是用现在已有资源组的方式,而是用跟 Snowflake 一样的架构,不同的节点去算不同的数据,相当于 OLAP 用一系列节点, ETL 用一系列节点,数据都存在 OSS 里边,这样能够保证两个 Workload 同时发生,但互不影响,这也是很多客户需要的。 目前 StarRocks 也在做多模的物化视图,包括增量的物化视图,流式的物化视图。 还有一些比较小的点,包括统一导入、半结构化数据。 以上就是本次分享的内容,谢谢大家。 点击立即免费试用云产品 开启云上实践之旅! 原文链接 本文为阿里云原创内容,未经允许不得转载。

优秀的个人博客,低调大师

探讨:在循环前与在循环中创建对象的区别

【业务场景】 后端从数据库中获取数据传给前端。 后端获得的数据格式:List 前端需求的数据格式:Json 【场景分析】 后端获取的数据格式为 List ,而前端需求的数据格式为 Json。因此,后端需要将数据重新组装为 Json 格式才能传给前端接收。而在数据重新组装的过程中会遇到这样的问题,在将对象从 List 逐个获取放入另一个 List 时,这个中间对象是在对 List 循环之前创建还是循环中创建。 这两种不同创建对象的方式会导致两种不同的组装效果。而这两种效果,一个是对的,一个是错的。 【示例代码】 代码运行环境 jdk: 1.8 插件:lombok 框架:springboot Item 实体 /** * Item 对象 */ @Data public class Item { private String ItemId;

优秀的个人博客,低调大师

Docker技术趋势解读

Docker使用Google公司推出的Go语言进行开发实现,基于Linux内核的cgroup,namespace,以及AUFS类的Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。 Docker在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。 Docker相较于传统的虚拟化方式有众多优势:1)更高效的利用系统资源;2)更快速的启动时间;3)一致的运行环境;4)持续交付和部署;5)执行环境一致性,更轻松的迁移;6)分层存储及镜像技术,使维护和扩展更轻松。 2016云栖大会上,生态系统开发总监John Willis,也是”DevOps” movement的发起人之一,从DevOps的做法和模式谈起,以分层堆栈程序间类比Docker,并通过图片举例说明中国是Docker交互的一部分,接着,结合图片分析Dockerizing应用,讲解Containers采用的3条路径。然后,分块展开介绍了Docker平台、开发者经验、业务流程、操作经验、Docker在Windows上应用等内容。欲知详情,且看下文PDF分解:

优秀的个人博客,低调大师

船舶电网谐波特性分析与有源滤波补偿方案技术探讨

船舶电网是由数台发电机组并联发电组成的独立电网。与陆地大电网相比,其短路容量显著降低,这使得船舶电气系统更容易受到谐波干扰的影响。随着舰载非线性用电设备尤其是雷达设备的数量增多、功率增大,注入舰船电网的谐波电流持续增大,电流总谐波含量高达27%,严重超出国军标GJB151A中CE101项目关于电流谐波限值的要求,并对其他较敏感的舰载用电设备造成不良影响或带来使用隐患。

优秀的个人博客,低调大师

干货分享丨从MPG 线程模型,探讨Go语言的并发程序

摘要:Go 语言的并发特性是其一大亮点,今天我们来带着大家一起看看如何使用 Go 更好地开发并发程序。 我们都知道计算机的核心为 CPU,它是计算机的运算和控制核心,承载了所有的计算任务。最近半个世纪以来,由于半导体技术的高速发展,集成电路中晶体管的数量也在大幅度增长,这大大提升了 CPU 的性能。著名的摩尔定律——“集成电路芯片上所集成的电路的数目,每隔18个月就翻一番”,描述的就是该种情形。 过于密集的晶体管虽然提高了 CPU 的处理性能,但也带来了单个芯片发热过高和成本过高的问题,与此同时,受限于材料技术的发展,芯片中晶体管数量密度的增加速度已经放缓。也就是说,程序已经无法简单地依赖硬件的提升而提升运行速度。这时,多核 CPU 的出现让我们看到了提升程序运行速度的另一个方向:将程序的执行过程分为多个可并行或并发执行的步骤,让它们分别在不同的 CPU 核心中同时执行,最后将各部分的执行结果进行合并得到最终结果。 并行和并发是计算机程序执行的常见概念,它们的区别在于: 并行,指两个或多个程序在同一个时刻执行; 并发,指两个或多个程序在同一个时间段内执行。 并行执行的程序,无论从宏观还是微观的角度观察,同一时刻内都有多个程序在 CPU 中执行。这就要求 CPU 提供多核计算能力,多个程序被分配到 CPU 的不同的核中被同时执行。 而并发执行的程序,仅需要在宏观角度观察到多个程序在 CPU 中同时执行。即使是单核 CPU 也可以通过分时复用的方式,给多个程序分配一定的执行时间片,让它们在 CPU 上被快速轮换执行,从而在宏观上模拟出多个程序同时执行的效果。但从微观角度来看,这些程序其实是在 CPU 中被串行执行。 Go 的 MPG 线程模型 Go 被认为是一门高性能并发语言,得益于它在原生态支持协程并发。这里我们首先了解进程、线程和协程这三者的联系和区别。 在多道程序系统中,进程是一个具有独立功能的程序关于某个数据集合的一次动态执行过程,是操作系统进行资源分配和调度的基本单位,是应用程序运行的载体。 而线程则是程序执行过程中一个单一的顺序控制流程,是 CPU 调度和分派的基本单位。线程是比进程更小的独立运行基本单位,一个进程中可以拥有一个或者以上的线程,这些线程共享进程所持有的资源,在 CPU 中被调度执行,共同完成进程的执行任务。 在 Linux 系统中,根据资源访问权限的不同,操作系统会把内存空间分为内核空间和用户空间:内核空间的代码能够直接访问计算机的底层资源,如 CPU 资源、I/O 资源等,为用户空间的代码提供计算机底层资源访问能力;用户空间为上层应用程序的活动空间,无法直接访问计算机底层资源,需要借助“系统调用”“库函数”等方式调用内核空间提供的资源。 同样,线程也可以分为内核线程和用户线程。内核线程由操作系统管理和调度,是内核调度实体,它能够直接操作计算机底层资源,可以充分利用 CPU 多核并行计算的优势,但是线程切换时需要 CPU 切换到内核态,存在一定的开销,可创建的线程数量也受到操作系统的限制。用户线程由用户空间的代码创建、管理和调度,无法被操作系统感知。用户线程的数据保存在用户空间中,切换时无须切换到内核态,切换开销小且高效,可创建的线程数量理论上只与内存大小相关。 协程是一种用户线程,属于轻量级线程。协程的调度,完全由用户空间的代码控制;协程拥有自己的寄存器上下文和栈,并存储在用户空间;协程切换时无须切换到内核态访问内核空间,切换速度极快。但这也给开发人员带来较大的技术挑战:开发人员需要在用户空间处理协程切换时上下文信息的保存和恢复、栈空间大小的管理等问题。 Go 是为数不多在语言层次实现协程并发的语言,它采用了一种特殊的两级线程模型:MPG 线程模型(如下图)。 MPG 线程模型 M,即 machine,相当于内核线程在 Go 进程中的映射,它与内核线程一一对应,代表真正执行计算的资源。在 M 的生命周期内,它只会与一个内核线程关联。 P,即 processor,代表 Go 代码片段执行所需的上下文环境。M 和 P 的结合能够为 G 提供有效的运行环境,它们之间的结合关系不是固定的。P 的最大数量决定了 Go 程序的并发规模,由 runtime.GOMAXPROCS 变量决定。 G,即 goroutine,是一种轻量级的用户线程,是对代码片段的封装,拥有执行时的栈、状态和代码片段等信息。 在实际执行过程中,M 和 P 共同为 G 提供有效的运行环境(如下图),多个可执行的 G 顺序挂载在 P 的可执行 G 队列下面,等待调度和执行。当 G 中存在一些 I/O 系统调用阻塞了 M时,P 将会断开与 M 的联系,从调度器空闲 M 队列中获取一个 M 或者创建一个新的 M 组合执行, 保证 P 中可执行 G 队列中其他 G 得到执行,且由于程序中并行执行的 M 数量没变,保证了程序 CPU 的高利用率。 M 和 P 结合示意图 当 G 中系统调用执行结束返回时,M 会为 G 捕获一个 P 上下文,如果捕获失败,就把 G 放到全局可执行 G 队列等待其他 P 的获取。新创建的 G 会被放置到全局可执行 G 队列中,等待调度器分发到合适的 P 的可执行 G 队列中。M 和 P 结合后,会从 P 的可执行 G 队列中无锁获取 G 执行。当 P 的可执行 G 队列为空时,P 才会加锁从全局可执行 G 队列获取 G。当全局可执行 G 队列中也没有 G 时,P 会尝试从其他 P 的可执行 G 队列中“剽窃”G 执行。 goroutine 和 channel 并发程序中的多个线程同时在 CPU 执行,由于资源之间的相互依赖和竞态条件,需要一定的并发模型协作不同线程之间的任务执行。Go 中倡导使用CSP 并发模型来控制线程之间的任务协作,CSP 倡导使用通信的方式来进行线程之间的内存共享。 Go是通过 goroutine 和 channel 来实现 CSP 并发模型的: goroutine,即协程,Go 中的并发实体,是一种轻量级的用户线程,是消息的发送和接收方; channel,即通道, goroutine 使用通道发送和接收消息。 CSP并发模型类似常用的同步队列,它更加关注消息的传输方式,解耦了发送消息的 goroutine 和接收消息的 goroutine,channel 可以独立创建和存取,在不同的 goroutine 中传递使用。 使用关键字 go 即可使用 goroutine 并发执行代码片段,形式如下: go expression 而 channel 作为一种引用类型,声明时需要指定传输数据类型,声明形式如下: var name chan T // 双向 channel var name chan <- T // 只能发送消息的 channel var name T <- chan // 只能接收消息的 channel 其中,T 即为 channel 可传输的数据类型。channel 作为队列,遵循消息先进先出的顺序,同时保证同一时刻只能有一个 goroutine 发送或者接收消息。 使用 channel 发送和接收消息形式如下: channel <- val // 发送消息 val := <- channel // 接收消息 val, ok := <- channel // 非阻塞接收消息 goroutine 向已经填满信息的 channel 发送信息或从没有数据的 channel 接收信息会阻塞自身。goroutine 接收消息时可以使用非阻塞的方式,无论 channel 中是否存在消息都会立即返回,通过 ok 布尔值判断是否接收成功。 创建一个 channel 需要使用 make 函数对 channel 进行初始化,形式如下所示: ch := make(chan T, sizeOfChan) 初始化 channel 时可以指定 channel 的长度,表示 channel 最多可以缓存多少条信息。下面我们通过一个简单例子演示 goroutine 和 channel 的使用: package main import ( "fmt" "time" ) //生产者 func Producer(begin, end int, queue chan<- int) { for i:= begin ; i < end ; i++ { fmt.Println("produce:", i) queue <- i } } //消费者 func Consumer(queue <-chan int) { for val := range queue { //当前的消费者循环消费 fmt.Println("consume:", val) } } func main() { queue := make(chan int) defer close(queue) for i := 0; i < 3; i++ { go Producer(i * 5, (i+1) * 5, queue) //多个生产者 } go Consumer(queue) //单个消费者 time.Sleep(time.Second) // 避免主 goroutine 结束程序 } 这是一个简单的多生产者和单消费的代码例子,生产 goroutine 将生产的数字通过 channel 发送给消费 goroutine。上述例子中,消费 goroutine 使用 for:range 从 channel 中循环接收消息,只有当相应的 channel 被内置函数 close 后,该循环才会结束。channel 在关闭之后不可以再用于发送消息,但是可以继续用于接收消息,从关闭的 channel 中接收消息或者正在被阻塞的 goroutine 将会接收零值并返回。还有一个需要注意的点是,main 函数由主 goroutine 启动,当主 goroutine 即 main 函数执行结束,整个 Go 程序也会直接执行结束,无论是否存在其他未执行完的 goroutine。 select 多路复用 当需要从多个 channel 中接收消息时,可以使用 Go 提供的 select 关键字,它提供类似多路复用的能力,使得 goroutine 可以同时等待多个 channel 的读写操作。select 的形式与 switch 类似,但是要求 case 语句后面必须为 channel 的收发操作,一个简单的例子如下: package main import ( "fmt" "time" ) func send(ch chan int, begin int ) { // 循环向 channel 发送消息 for i :=begin ; i< begin + 10 ;i++{ ch <- i } } func receive(ch <-chan int) { val := <- ch fmt.Println("receive:", val) } func main() { ch1 := make(chan int) ch2 := make(chan int) go send(ch1, 0) go receive(ch2) // 主 goroutine 休眠 1s,保证调度成功 time.Sleep(time.Second) for { select { case val := <- ch1: // 从 ch1 读取数据 fmt.Printf("get value %d from ch1\n", val) case ch2 <- 2 : // 使用 ch2 发送消息 fmt.Println("send value by ch2") case <-time.After(2 * time.Second): // 超时设置 fmt.Println("Time out") return } } } 在上述例子中,我们使用 select 关键字同时从 ch1 中接收数据和使用 ch2 发送数据,输出的一种可能结果为: get value 0 from ch1 get value 1 from ch1 send value by ch2 receive: 2 get value 2 from ch1 get value 3 from ch1 get value 4 from ch1 get value 5 from ch1 get value 6 from ch1 get value 7 from ch1 get value 8 from ch1 get value 9 from ch1 Time out 由于 ch2 中的消息仅被接收一次,所以仅出现一次“send value by ch2”,后续消息的发送将被阻塞。select 语句分别从 3 个 case 中选取返回的 case 进行处理,当有多个 case 语句同时返回时,select 将会随机选择一个 case 进行处理。如果 select 语句的最后包含 default 语句,该 select 语句将会变为非阻塞型,即当其他所有的 case 语句都被阻塞无法返回时,select 语句将直接执行 default 语句返回结果。在上述例子中,我们在最后的 case 语句使用了 <-time.After(2 * time.Second) 的方式指定了定时返回的 channel,这是一种有效从阻塞的 channel 中超时返回的小技巧。 Context 上下文 当需要在多个 goroutine 中传递上下文信息时,可以使用 Context 实现。Context 除了用来传递上下文信息,还可以用于传递终结执行子任务的相关信号,中止多个执行子任务的 goroutine。Context 中提供以下接口: type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{} } Deadline 方法,返回 Context 被取消的时间,也就是完成工作的截止日期; Done,返回一个 channel,这个channel 会在当前工作完成或者上下文被取消之后关闭,多次调用 Done 方法会返回同一个 channel; Err 方法,返回 Context 结束的原因,它只会在 Done 返回的 channel 被关闭时才会返回非空的值,如果 Context 被取消,会返回 Canceled 错误;如果 Context 超时,会返回 DeadlineExceeded 错误。 Value 方法,可用于从 Context 中获取传递的键值信息。 在 Web 请求的处理过程中,一个请求可能启动多个 goroutine 协同工作,这些 goroutine 之间可能需要共享请求的信息,且当请求被取消或者执行超时时,该请求对应的所有 goroutine 都需要快速结束,释放资源。Context 就是为了解决上述场景而开发的,我们通过下面一个例子来演示: package main import ( "context" "fmt" "time" ) const DB_ADDRESS = "db_address" const CALCULATE_VALUE = "calculate_value" func readDB(ctx context.Context, cost time.Duration) { fmt.Println("db address is", ctx.Value(DB_ADDRESS)) select { case <- time.After(cost): // 模拟数据库读取 fmt.Println("read data from db") case <-ctx.Done(): fmt.Println(ctx.Err()) // 任务取消的原因 // 一些清理工作 } } func calculate(ctx context.Context, cost time.Duration) { fmt.Println("calculate value is", ctx.Value(CALCULATE_VALUE)) select { case <- time.After(cost): // 模拟数据计算 fmt.Println("calculate finish") case <-ctx.Done(): fmt.Println(ctx.Err()) // 任务取消的原因 // 一些清理工作 } } func main() { ctx := context.Background(); // 创建一个空的上下文 // 添加上下文信息 ctx = context.WithValue(ctx, DB_ADDRESS, "localhost:10086") ctx = context.WithValue(ctx, CALCULATE_VALUE, 1234) // 设定子 Context 2s 后执行超时返回 ctx, cancel := context.WithTimeout(ctx, time.Second * 2) defer cancel() // 设定执行时间为 4 s go readDB(ctx, time.Second * 4) go calculate(ctx, time.Second * 4) // 充分执行 time.Sleep(time.Second * 5) } 在上述例子中,我们模拟了一个请求中同时进行数据库访问和逻辑计算的操作,在请求执行超时时,及时关闭尚未执行结束 goroutine。我们首先通过 context.WithValue 方法为 context 添加上下文信息,Context 在多个 goroutine 中是并发安全的,可以安全地在多个 goroutine 中对 Context 中的上下文数据进行读取。接着使用 context.WithTimeout 方法设定了 Context 的超时时间为 2s,并传递给 readDB 和 calculate 两个 goroutine 执行子任务。在 readDB 和 calculate 方法中,使用 select 语句对 Context 的 Done 通道进行监控。 由于我们设定了子 Context 将在 2s 之后超时,所以它将在 2s 之后关闭 Done 通道;然而预设的子任务执行时间为 4s,对应的 case 语句尚未返回,执行被取消,进入到清理工作的 case 语句中,结束掉当前的 goroutine 所执行的任务。预期的输出结果如下: calculate value is 1234 db address is localhost:10086 context deadline exceeded context deadline exceeded 使用 Context,能够有效地在一组 goroutine 中传递共享值、取消信号、deadline 等信息,及时关闭不需要的 goroutine。 小结 本文我们主要介绍了 Go 语言并发特性,主要包含: Go 的 MPG 线程模型; goroutine 和 channel; select 多路复用; Context 上下文。 除了支持 CSP 的并发模型,Go 同样支持传统的线程与锁并发模型,提供了互斥锁、读写锁、并发等待组、同步等待条件等一系列同步工具,这些同步工具的结构体位于 sync 包中,与其他语言的同步工具使用方式相差无几。Go 在语言层次支持协程并发,在并发性能上表现卓越,能够充分挖掘多核 CPU 的运算性能。希望本节课的学习,能够有效提升你对 Go 并发设计和编程的认知。 本文分享自华为云社区《如何使用 Go 更好地开发并发程序》,原文作者:aoho 。 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

《人民日报》发文探讨区块链,新风口还是概念炒作?

《人民日报》三问区块链,表明坚定立场:积极拥抱新事物,理性警惕概念炒作、集资圈钱等违法犯罪行为。 近几年来,关于区块链与比特币的传闻一直甚嚣尘上,有江湖的地方就有比特币,有比特币的地方就有区块链。但是,很多人总是跟随着大部队“淘金”,或兴奋,或后悔,或焦灼观望,却并不知道区块链到底是什么?有什么用?为何有如此大的投资价值? 在三月份两会将要召开的当口,《人民日报》三问区块链,表明官方的坚定立场:积极拥抱新事物,理性警惕概念炒作、集资圈钱等违法犯罪行为。 区块链第一问,“江湖传说—神秘的区块链”:《人民日报》给出的区块链广义定义是一种新的分布式基础架构和计算范式,即其本质是一种计算范式。这种计算范式有其特殊的块链式数据结构,能够验证和存储数据。其还能够利用分布式节点共识算法来生成和更新数据,保证数据传输和访问安全。 看上去有些复杂的定义,简单来说,就像是上学时学的某个公式或定理,只要有数据就能套用里面,得出某种结果,而这种结果能帮我们解决实际问题。 关于第二问和第三问,《人民日报》肯定了区块链技术在金融、公益、监管、大家等多领域痛点难点的积极作用。很明显,区块链技术能够帮助不同领域高效透明而安全的运作。而第三问担忧的是目前区块链技术的不成熟和应用场景有限,但是却被目的不单纯的人用来集资圈钱、炒作估值。 勒庞的在《乌合之众》中曾描述,个人一旦进入一个集体,个性会被湮灭,很容易受到情绪左右,不明所以地投入到一场激烈的运动中去,产生破坏性社会后果。即使如此,“因噎废食”毕竟不可取,政府在观望几年后,理性接纳区块链,扶持和发展,警惕和监管,双管齐下。 在这样的信号下,跟着区块链走的大部队们或许有所启发。 以下是《人民日报》刊发的原文: 近段时间,有关比特币的新闻非常吸睛,区块链也跟着火了一把。资本市场上,各种区块链概念股的股价涨跌犹如过山车般惊心动魄。从反应敏锐的资本市场可以看出,区块链正站上风口,受到各方高度关注。 什么是区块链? 一种去中心化的分布式账本数据库,没有中心,数据存储的每个节点都会同步复制整个账本,信息透明难以篡改 近几年,越来越多的机构开始重视并参与区块链技术研发。从最初的比特币、以太坊,到各种类型的区块链创业公司、风险投资基金、金融机构,贴上“区块链”标签,立马就“金光闪闪”。不仅如此,很多人的微信朋友圈也被各种解读区块链的文章刷屏。 那么,到底什么是区块链? 工信部指导发布的《中国区块链技术和应用发展白皮书2016》这样解释:广义来讲,区块链技术是利用块链式数据结构来验证与存储数据、利用分布式节点共识算法来生成和更新数据、利用密码学的方式保证数据传输和访问的安全、利用由自动化脚本代码组成的智能合约来编程和操作数据的一种全新的分布式基础架构与计算范式。 交通银行金融研究中心高级研究员何飞进行了通俗解释:“简单地说,区块链就是一种去中心化的分布式账本数据库。”去中心化,即与传统中心化的方式不同,这里是没有中心,或者说人人都是中心;分布式账本数据库,意味着记载方式不只是将账本数据存储在每个节点,而且每个节点会同步共享复制整个账本的数据。同时,区块链还具有去中介化、信息透明等特点。 “区块链技术本质上是一种数据库技术,具体讲就是一种账本技术。账本记录一个或多个账户资产变动、交易情况,其实是一种结构最为简单的数据库,我们平常在小本本上记的流水账、银行发过来的对账单,都是典型的账本。”腾讯金融科技智库首席研究员王钧说,安全是区块链技术的一大特点,主要体现在两方面:一是分布式的存储架构,节点越多,数据存储的安全性越高;二是其防篡改和去中心化的巧妙设计,任何人都很难不按规则修改数据。 以网购交易为例,传统模式是买家购买商品,然后将钱打到第三方支付机构这个中介平台,等卖方发货、买方确认收货后,再由买方通知支付机构将钱打到卖方账户。由区块链技术支撑的交易模式则不同,买家和卖家可直接交易,无需通过任何中介平台。买卖双方交易后,系统通过广播的形式发布交易信息,所有收到信息的主机在确认信息无误后记录下这笔交易,相当于所有的主机都为这次交易做了数据备份。即使今后某台机器出现问题,也不会影响数据的记录,因为还有无数台机器作为备份。 提到区块链,很多人就把它与比特币联系在一起,不少人甚至把区块链等同为比特币。何飞说,比特币是区块链的一种呈现方式,但区块链并不等同于比特币。区块链是比特币的底层技术和基础架构,而比特币是区块链的成功应用,但并不意味着区块链只能应用到比特币上。 区块链有什么用? 能解决金融、公益、监管、打假等很多领域的痛点难点,但有不少适用条件 金融服务是区块链技术的第一个应用领域。运用区块链技术能解决支付、资产管理、证券等多个领域存在的痛点。 以支付领域为例,金融机构特别是跨境金融机构间的对账、清算、结算的成本较高,涉及很多手工流程,不仅导致用户端和金融机构后台业务端等产生高昂的费用,也使得小额支付业务难以开展。区块链技术的应用有助于降低金融机构间的对账成本及争议解决的成本,显著提高支付业务的处理效率。另外,区块链技术为支付领域带来的成本和效率优势,使金融机构能更好处理以往因成本过高而被视为不现实的小额跨境支付,有助于实现普惠金融。 比如,为解决金融机构间对账成本高的问题,2016年8月,微众银行联合上海华瑞银行推出微粒贷机构间对账平台,这也是国内首个在生产环境中运行的银行业联盟链应用场景。微众银行区块链首席架构师张开翔认为,传统“批量文件对账”模式长久以来未能解决的成本高问题,正是区块链技术的用武之地。随后,洛阳银行、长沙银行也相继接入机构间对账平台,通过区块链技术,优化微粒贷业务中的机构间对账流程,实现了准实时对账、提高运营效率、降低运营成本等目标。截至目前,平台稳定运行1年多,保持零故障,记录的真实交易笔数已达千万量级。 在公益领域,区块链技术也大有可为。蚂蚁金服涉及区块链的首个应用场景就是公益,帮助一群听障儿童获得一笔善款,然后运用区块链技术促进公益更加开放透明。蚂蚁金服技术实验室高级产品专家胡丹青说:“区块链公益平台就像是我们在互联网上构建了一个专门用于邮寄资金的邮局。用户捐的每一笔钱,我们都会打包成一个包裹,这个包裹通过区块链平台传递,每经过一个节点,我们都会盖上一个邮戳,最后送到受捐人手上。这样可以保证用户捐的每一笔钱都是透明、可追溯、难以篡改的。” 在商品打假方面,区块链技术可以大显身手。胡丹青介绍,蚂蚁金服将区块链技术用在了正品溯源上。目前,已有部分来自澳大利亚、新西兰的海淘商品比如奶粉,用支付宝扫一扫,就能知道是不是正品。“跟此前商家自录入商品信息不同的是,区块链是让多位‘记账师’公正、独立、不可抵赖地完成记账。” 对于金融监管,区块链技术也能发挥一技之长。2017年金融区块链合作联盟(深圳)发布的《金融区块链底层平台FISCO BCOS白皮书》认为,区块链为金融监管机构提供了一致且易于审计的数据,通过对机构间区块链的数据分析,能够比传统审计流程更快更精确地监管金融业务。例如,在反洗钱场景中,每个账号的余额和交易记录都是可追踪的,任意一笔交易的任何一个环节都不会脱离监管视线,这将极大提高反洗钱的力度。 有业内人士认为,区块链1.0主要针对数字货币;区块链2.0针对智能合约,可以应用在金融市场中;区块链3.0适用的场景将会更多,甚至会开创一个“区块链时代”。 何飞认为,区块链确实能解决很多领域的痛点难点,但区块链不是万能的,也有很多适用条件。 比如,区块链技术去中心化的特点适合多方参与的场景,如果只是单边或双边参与价值就不大。由于需要每个节点都去核对,区块链技术也不适用那些高频交易的活动。 再如,区块链强调的是公开透明,并不适合对数据隐私要求特别高的场景。 区块链会成新风口吗? 技术目前还不太成熟,要警惕概念炒作,特别要区分是技术创新还是集资创新,不能为了区块链而区块链 区块链概念这么火,未来会成为又一个“互联网+”吗? 近年来,区块链的发展生态逐渐得到改善与丰富。业内人士认为,拥有国家政策扶持,得到广泛关注和资金支持,区块链技术能实现逐步稳定进步。区块链技术上行前景虽广阔,但对此也要保持一颗平常心。 “尽管眼下区块链大热,但我们仍然认为,它还处于一个非常早期的阶段。”胡丹青说,区块链概念目前存在虚热,不是热在拿技术解决现实问题,而是热在集资圈钱、炒作估值,尤其是热炒的绝大部分所谓ICO(首次代币发行)都是集资工具创新,跟技术创新无关。 区块链技术确实能创造很大的价值,但一些风险也不容忽视。 “区块链技术还不太成熟,可应用场景比较有限,更应警惕资本市场炒作概念。”何飞说,区块链热潮的背后免不了会有一些搞噱头想投机的公司,他们并没有真正开展业务,只是企图到资本市场捞一笔就走,要谨防由此出现“劣币驱逐良币”,导致真正想开展业务的机构退出市场,影响区块链技术的应用。 胡丹青建议,对于目前的区块链热,监管部门应更主动地介入,区分是技术创新还是集资创新,鼓励政府组织、有公信力的专家、行业参与者共同帮助公众辨识,全面遏制区块链名义下的集资创新,让ICO实际控制人必须为集资行为承担责任。“判断是技术创新还是集资创新的依据其实很清楚,即是否以信任为始,是否通过解决信任问题创造了实际价值。” 今后更好地推广和使用区块链技术,还需继续完善基础设施、加强相关法律政策制定等。 王钧认为,共识算法等区块链的核心技术尚存在优化和完善的空间;另一方面,区块链的处理效率还难以达到现实中一些高频度应用环境的要求。目前主流的区块链技术平台均发源于国外,国内的区块链技术服务商要耐心地从底层开发做起,做到技术自主可控,争取引领全球区块链技术发展。拥有区块链应用场景的企业,要积极拥抱新事物,同时科学评估上链需求,不能为了区块链而区块链。 何飞认为,政府可以出台相关政策,指导有志于投身区块链技术研发应用的企业,同时明确一些区块链适合应用的场景及国家鼓励的领域等。 《中国区块链技术和应用发展白皮书2016》建议各级政府主管部门借鉴发达国家和地区的先进做法,结合我国区块链技术和应用发展情况,及时出台区块链技术和产业发展扶持政策,重点支持关键技术攻关、重大示范工程、“双创”平台建设、系统解决方案研发和公共服务平台建设等。同时,建议国内重点企业、科研、高校和用户单位加强联合,加快共识机制、可编程合约、分布式存储、数字签名等核心关键技术攻关。 原文发布时间: 2018-02-26 11:55 本文作者: Lotusun 本文来自云栖社区合作伙伴镁客网,了解相关信息可以关注镁客网。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册