PhpStorm 2022.3 现已正式发布,此次更新带来了新 UI 的预览、完整的 PHP 8.2 支持、数据库工具中的 Redis 支持、PHP 的代码视觉、快速修复预览、Xdebug 配置验证、对 ParaTest 的支持、PHPDoc 的阅读器模式以及许多其他功能。
新 UI
全新的用户界面现已开放试用,新 UI 仍处于 Beta 阶段,默认关闭,可以在设置/首选项 中切换到新的 UI。
PHP 8.2
PhpStorm 2022.3 完全支持 PHP 8.2,包含以下功能:
- 对只读类的各项支持
- 访问不存在的属性将导致弃用通知
- 添加了对析取范式类型以及独立的 null、true 和 false 类型的支持
- 可以使用 #[SensitiveParameter] 属性标记敏感参数
- 弃用 ${ 字符串插值
改进的快速文档
按下F1 / Ctrl+Q任何函数、类或方法,PhpStorm 将直接在编辑器中显示文档。
日期时间格式预览
将鼠标悬停在日期格式字符串上时,PhpStorm 2022.3 会显示带有示例日期的工具提示。
以上为此版本部分新功能,更多内容可以在发布公告中查阅。
🍈项目介绍
项目地址:https://gitee.com/bootx/bootx-platform,非常欢迎看看项目介绍留以及个Star呀🤺🤺🤺
基于Spring Boot框架打造,针对单体式应用进行专门设计,提供整套服务模块,支持支付收单(支付宝、微信、聚合、组合支付)、工作流(Flowable)、三方对接(微信、钉钉、企微、短信)等模块,后端基于Spring Boot和Spring Cloud,前端基于Vue2和Vue3分别打造,可应用在不同业务场景中,目标致力将开源版打造成超越商业后台管理框架的脚手架。
Spring Cloud版本使用Spring Cloud Alibaba技术栈
vue2使用ANTD PRO VUE 作为脚手架
vue3使用 Vben-Admin-Next 作为脚手架
移动端使用 Taro ue3+TS为技术栈
🛠️本次功能更新
项目主要更新
- 优化: 升级基础依赖
- 优化: redisson启动机制修改, 不再会导致项目无法启动
- 优化: 钱包报错提示优化
- 优化: vue3模板调整
- fix ts映射字段类型缺失
Vue3进度
- 新增: 企业微信机器人和钉钉机器人配置
- 新增: 新增a-link组件,替代标签
- 新增: 除流程图设计之外的流程基础配置
- 新增: 消息通知查看和未读列表
- 新增: 添加wangEditor组件
- 新增: 用户全局websocket消息推送
- 新增: 菜单支持配置单独打开内部页面
- 新增: 菜单支持配置在内部打开外部页面
- 新增: 消息模板渲染测试功能
- 新增: 微信支付通道配置
- 新增: 支付宝支付通道配置
- 新增: 超级查询器及演示DEMO
- 新增: 微信支付通道
- 新增: 支付记录/退款记录/回调记录
- 新增: 储值卡管理
- 新增: 钱包管理
- 新增: 简单复杂和简单结算台演示Demo
- 优化: 字典初始化提早到项目加载时
- 优化: 用户和角色选择器新增数据源属性配置项
- 优化: basic-modal 最低高度为无限制
- 优化: 项目路由配置,无用代码删除
Vue2更新
- 优化: 用户和角色选择器新增数据源属性配置
- 优化: diffForm逻辑重构
- 优化: 表单提示补全
- 优化: 富文本功能样式优化
- 优化: 部分请求地址变更
- 优化: 错误命名和无用代码修正
- 优化: 超级查询器文本更新, 菜单编辑校验格式优化
🚅 路线图
- 工作流功能完善【完成】
- Vue3 版本前端【进行中,进度75%】
- 基础功能补全【进行中】
- 短信通知对接
- minio对接
- 文档预览功能对接
- 自定义报表大屏
- 认证控制功能优化,支持登录错误次数锁定,二次操作验证等
- Spring Cloud 版本【规划中】
- 代码组织结构调整 [完成]
- 网关定制开发 [完成]
- 功能模块移植 [进行中]
🥞功能截图
| | | | | | | | | |
| | | | | | | |
漏洞描述
Cacti 是一个开源平台,可为用户提供强大且可扩展的操作监控和故障管理框架。
在Cacti受影响版本中,由于$poller_id参数可控且未做过滤处理,导致用户可通过该控制该参数满足poller_item = POLLER_ACTION_SCRIPT_PHP,进而proc_open函数触发,执行任意代码。如果为任何受监控设备选择了特定数据源,未经身份验证的攻击者可在运行 Cacti 的服务器上执行任意代码。
影响范围
cacti@[1.2.22, 1.2.23)
cacti@[1.2.22, 1.3.0)
修复方案
将组件 cacti 升级至 1.2.23 及以上版本
将组件 cacti 升级至 1.3.0 及以上版本
参考链接
https://www.oscs1024.com/hd/MPS-2022-65562
Commit
Commit
NVD
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
漏洞描述
Cacti 是一个开源平台,可为用户提供强大且可扩展的操作监控和故障管理框架。
在Cacti受影响版本中,由于$poller_id参数可控且未做过滤处理,导致用户可通过该控制该参数满足poller_item = POLLER_ACTION_SCRIPT_PHP,进而proc_open函数触发,执行任意代码。如果为任何受监控设备选择了特定数据源,未经身份验证的攻击者可在运行 Cacti 的服务器上执行任意代码。
影响范围
cacti@[1.2.22, 1.2.22]
修复方案
参考链接
https://www.oscs1024.com/hd/MPS-2022-65562
Commit
Commit
NVD
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
漏洞描述
Node.js 是一个开源、跨平台的 JavaScript 运行时环境。
Node.js 18.7.0版本中的 http 模块中存在 HTTP 请求走私漏洞,漏洞源于 llhttp 解析器无法正确处理未以 CLRF 终止的标头字段,攻击者可通过恶意构造位于 之前、包含空值且未正确使用 CLRF 进行分隔的 http 请求标头触发此漏洞。攻击者可利用此漏洞获取 web 程序敏感信息,并获得对 web 应用程序的未授权访问。
影响范围
nodejs@[18.0.0, 18.12.1]
nodejs@[14.0.0, 14.21.1]
nodejs@[16.0.0, 16.18.1]
nodejs/llhttp@(-∞, 6.0.10)
修复方案
nodejs 暂未发布新版本,请关注官方公告:https://nodejs.org/en/blog/
升级nodejs/llhttp到 6.0.10 或更高版本
参考链接
https://www.oscs1024.com/hd/MPS-2022-50637
https://nvd.nist.gov/vuln/detail/CVE-2022-35256
https://hackerone.com/reports/
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
每当TIOBE榜单发布的时候,那个笑话就会回响在开源社区诸位的耳边:
美女:你能一句话让这个社区的人吵起来我今晚跟你走。
程序员:PHP是最好的语言。
美女:我跟你走。
程序员:不行,我得说服他们PHP是最好的语言。
这就让我们产生了一个问题,即使这份榜单20名开外的语言的开发者也会参与这样的吵架么?他们的开源活动的策略和估计是什么?本文作者作为scheme-langserver的开发者,希望在这里为大家做一点分享。以下为原文:
在对于中国开源运动的估计和伴随而来的行为策略问题上,开源社区的人们还没有进行系统的梳理过。大家虽然相信开源的盘子是不可避免的越来越大的,却更多的是把这种运动当成一种“电子榨菜”。因此他们实际上不赞成对开源运动进行深入的参与,只想要蜻蜓点水,能够在求职的时候打一打游击,能快速找到几个Java、Python或者PHP项目解决需求就好了。同时,他们也没有把自己独特的想法和创造性贡献给开源社区的意愿,因此也就没有这种开源运动会快速发展去促成全信息技术产业链高度变革的观念。他们似乎认为开源运动对于改善自己的职业生涯是有益但是有限的,至少对于遥远的35岁危机和996工时是徒劳的。他们最多用比较轻便的“使用-宣传-拉人头”的循环扩大开源的影响,等到他们所谓全国乃至全世界的工作都做好了,或者做到某个地步了,再“咔”一声把旗帜举起来就能促成自己对封闭的、陈旧的、没有人道主义精神的不自由996式样的开发的颠覆。
他们这种全领域的,包括一切地方的、拉人头式样的开源活动的理论是不切合实际的。这种不切合实际的幻想主要是因为对于一个事实没有认知清楚:企业和组织正在把开源当成一种KPI,而且从2014年开始已经当成了KPI(据《中国开源报告2022》)——也就是说,对开源产品的“使用-宣传-拉人头”是他们在学校里听到的关于就业的神话;是过去一段时间企业之间抢夺人才优势织造的一个梦;是2022年知乎上所谓计算机行业失业大潮戳破的一个泡泡——唯独不是绝大多数开源产品使用者的自觉。他们是跟着走的羊,在吃草的时候故意不去看狼或者牧羊犬。
如果认识清楚了当前中国乃至国外的开源活动越来多的成为许多企业互相争夺的“半殖民地”而不是社区的“自留地”,则:第一,就会明白为什么Gitee会宣称所谓的“全球第二大开源社区”而许多人从未向某一开源项目提交过一个pull request;第二,就会明白把明白为什么开源中国的“综合资讯”主要是各大企业的新闻自留地,“软件更新资讯”评论最多的软件往往是Web、大前端,即使开源中国置顶了《如何在 OSC 社区运营你的开源项目?》而不是《如何在 OSC 社区运营企业的开源项目?》;第三就会明白为什么还会有TIOBE12月榜单上排名20开外的语言的项目在活跃;第四,就会明白为什么硅谷仍然是创新的中心而不是什么深圳或者北京;第五,就会明白写一些小众语言的代码,构成企业使用这些代码的技术壁垒是一种必要的形式。
这等等等等的事实都说明,要在程序员所谓“已经很高”的工资收入基础上继续改善程序员的生活,要挣得自己的劳动所创造的比较大的那一部分,就必须在当前开源社区已经占据的广大地域,用小众的语言去开发更多的东西:可以是网站,可以是APP,可以是视频剪辑软件。要用曾经弱小的社区能够壮大来教育自己,用更加紧密的团结、更加丰富的开发和“多样性”倒逼市场提高待遇——让不是市场主体的自己享受更多利好。特别是某些市场主体已经展露了吃白食的獠牙的时候。
当然也不必犯反主流文化的急性病。控制论曾经将计算、反主流文化和设计联系起来,就仿佛美国6、70年代的披头士们诞生了苹果一样,大企业对于小众需求的傲慢和无视渐渐孕育了伟大的反抗和伟大的下一代,这就是中学政治课本里面的矛盾论。在当代这种孕育是什么我们并不知道,但是如果开源社区有这样的意愿,我们也将在历史中学习和塑造自己的能力。
让一切不够尊重开源和程序员的人发抖吧。星星之火,可以燎原。
导读: Apache Doris 是小米集团内部应用最为广泛的 OLAP 引擎之一,本文主要从数据的角度分析 A/B 实验场景查询的性能现状,探讨基于 Apache Doris 的性能优化的解决方案。经过一系列基于 Doris 的性能优化和测试,A/B 实验场景查询性能的提升超过了我们的预期。希望本次分享可以给有需要的朋友提供一些参考。
作者|小米集团大数据工程师 乐涛
业务背景
A/B 实验是互联网场景中对比策略优劣的重要手段。为了验证一个新策略的效果,需要准备原策略 A 和新策略 B 两种方案。随后在总体用户中取出一小部分,将这部分用户完全随机地分在两个组中,使两组用户在统计角度无差别。将原策略 A 和新策略 B 分别展示给不同的用户组,一段时间后,结合统计方法分析数据,得到两种策略生效后指标的变化结果,并以此判断新策略 B 是否符合预期。
小米 A/B 实验平台是一款通过 A/B 实验的方式,借助实验分组、流量拆分与科学评估来辅助完成科学的业务决策,最终实现业务增长的一款运营工具产品。其广泛的应用于产品研发生命周期中各个环节:
数据平台架构
本文主要从数据的角度分析 A/B 实验场景查询的性能现状,探讨一下基于 Apache Doris 的性能优化的解决方案。A/B实验平台的架构如下图所示:
- 平台使用的数据主要包含平台自用的实验配置数据、数据,以及业务方上报的日志数据。
- 由于业务方引入 SDK,并与分流服务进行交互,日志数据中包含其参与的实验组 ID 信息。
- 用户在实验平台上配置、分析、查询,以获得报告结论满足业务诉求。
鉴于 AB 实验报告各个业务方上报数据的链路都大体类似,我们就拿头部业务方广告业务举例,数据流程如下图所示:
从上图可知,整个数据链路并不复杂,日志数据传入后,经过必要的数据处理和清洗工作进入 Talos(小米自研消息队列),通过 Flink 任务以明细数据的形式实时写入到 Doris 表中,同时 Talos 数据也会同步到 Hive 表进行备份,以便问题排查和数据修复。
出于对高效写入以及字段增减需求的考虑,Doris 明细表以 Duplicate 模型来建模:
在提速之前,小米 A/B 实验平台完成实验报告查询的 P95 时间为小时级,实验报告使用数据的方式存在诸多的性能问题,直接影响业务部门做运营和决策的效率。
报告查询基于明细
当前报告查询的数据来源为明细表,而明细表的数据量巨大:
而且,实验报告的查询条件中时间范围常常横跨多天。基于历史查询报告统计,查询条件中时间范围大于一天的报告占比 69.1%,具体的时间跨度占比分布如下:
明细数据的巨大扫描量给集群带来了不小的压力,且由于报告查询存在并发以及 SQL 的拆分,如果一个 SQL 请求不能快速的返回结果释放资源,也会影响到请求的排队状况。因此在工作时间段内 Doris 集群BE节点 CPU 负载状况基本是持续满载,磁盘 IO 也持续处于高负荷状态,如下图所示:
BE节点CPU使用率
BE节点磁盘IO
个人思考:
- 当前报告所有查询基于明细数据,且平均查询时间跨度为 4 天,查询扫描数据量上百亿。由于扫描数据量级大,计算成本高,给集群造成较大压力,导致数据查询效率不高。
- 如果通过对数据进行预聚合处理,控制 Scan Rows 和 Scan Bytes,减小集群的压力,查询性能会大幅提升。
字段查询热度分层分布
由于之前流程管控机制相对宽松,用户添加的埋点字段都会进入到明细表中,导致字段冗余较多。统计历史查询报告发现,明细表中常用的维度和指标只集中在部分字段,且查询热度分层分布:
参与计算的指标也集中在部分字段,且大部分都是聚合计算(sum)或可以转化为聚合计算(avg):
个人思考:
- 明细表中参与使用的维度只占 54.3%,高频使用的维度只占 15.2%,维度查询频次分层分布。
- 数据聚合需要对明细表中维度字段做取舍,选择部分维度进行上卷从而达到合并的目的,但舍弃部分字段必然会影响聚合数据对查询请求的覆盖情况。而维度查询频次分层分布的场景非常适合根据维度字段的热度做不同层次的数据聚合,同时兼顾聚合表的聚合程度和覆盖率。
实验组 ID 匹配效率低
当前明细数据的格式为:
明细数据中的实验组 ID 以逗号分隔的字符串形式聚拢在一个字段中,而实验报告的每条查询语句都会使用到过滤,查询数据时使用 LIKE 方式匹配,查询效率低下。
个人思考:
- 将实验组 ID 建模成一个单独的维度,可使用完全匹配代替 LIKE 查询,且可利用到 Doris 索引,提高数据查询效率。
- 将逗号分隔的实验组 ID 直接打平会引起数据量的急剧膨胀,因此需要设计合理的方案,同时兼顾到数据量和查询效率。
进组人数计算有待改进
进组人数查询是实验报告的必查指标,因此其查询速度很大程度上影响实验报告的整体查询效率,当前主要问题如下:
- 当进组人数作为独立指标计算时,使用近似计算函数处理,是通过牺牲准确性的方式提升查询效率。
- 当进组人数作为复合指标的分母进行计算时,使用处理,此方式在大数据量计算场景效率较低。
个人思考:
- AB实验报告的数据结论会影响到用户决策,牺牲准确性的方式提升查询效率是不可取的,特别是广告这类涉及金钱和业绩的业务场合,用户不可能接受近似结果。
- 进组人数使用的计算需要依赖明细信息,这也是之前查询基于明细数据的重要因素。必须为此类场景设计新的方案,使进组人数的计算在保证数据准确的前提下提高效率。
数据优化方案
基于以上的数据现状,我们优化的核心点是将明细数据预聚合处理,通过压缩数据来控制 Doris 查询的 Scan Rows 和 Scan Bytes。与此同时,使聚合数据尽可能多的覆盖报告查询。从而达到,减小集群的压力,提高查询效率的目的。
新的数据流程如下图所示:
整个流程在明细链路的基础上增加聚合链路,Talos 数据一方面写入 Doris 明细表,另一方面增量落盘到 Iceberg 表中,Iceberg 表同时用作回溯明细数据以及生成聚合数据,我们通过工场 Alpha(小米自研数据开发平台)的实时集成和离线集成保证任务的稳定运行和数据的一致性。
选取高频使用维度聚合
在生成数据聚合的过程中,聚合程度与请求覆盖率是负相关的。使用的维度越少,能覆盖的请求就越少,但数据聚合程度越高;使用的维度越多,覆盖的请求也越多,但数据粒度就越细,聚合程度也越低。因此需要在聚合表建模的过程中取得一个平衡。
我们的具体做法是:拉取历史(近半年)查询日志进行分析,根据维度字段的使用频次排序确认进入聚合表的优先级。在此基础上得出聚合表的覆盖率和数据量随着建模字段增加而变化的曲线,如下图所示:
其中覆盖率根据历史请求日志代入聚合表计算得出。
我们的原则是:针对 OLAP 查询,聚合表的数据量应尽可能的控制在单日 1 亿条以内,请求覆盖率尽可能达到 80%以上。
因此不难得出结论:选择 14 个维度字段对聚合表建模比较理想,数据量能控制到单日 8 千万条左右,且请求覆盖率约为 83% 。
使用物化视图
在分析报告历史查询日志时,我们发现不同的维度字段查询频次有明显的分层:
Top7 维度字段几乎出现在所有报告的查询条件之中,对于如此高频的查询,值得做进一步的投入,使查询效率尽可能的提升到最佳。Doris 的物化视图能够很好的服务于此类场景。
什么是物化视图?
物化视图是一种特殊的物理表,其中保存基于基表(base table)部分字段进一步上卷聚合的结果。
虽然在物理上独立存储,但它是对用户透明的。为一张基表配置好物化视图之后,不需要为其写入和查询做任何额外的工作:
- 当向基表写入和更新数据时,集群会自动同步到物化视图,并通过事务方式保证数据一致性。
- 当对基表进行查询时,集群会自动判断是否路由到物化视图获取结果。当查询字段能被物化视图完全覆盖时,会优先使用物化视图。
因此我们的查询路由如下图所示:
用户的查询请求会尽可能的路由到聚合表物化视图,然后是聚合表基表,最后才是明细表。
如此使用多梯度的聚合模型的配合来应对热度分层的查询请求,使聚合数据的效能尽可能的发挥到最大。
精确匹配取代 LIKE 查询
既然物化视图这么好用,为什么我们不是基于 Doris 明细表配置物化视图,而是单独开发聚合表呢?是因为明细数据中的实验组ID字段存储和查询方式并不合理,聚合数据并不适合通过明细数据直接上卷来得到。
上文中已经提到,(实验组ID)在明细表中以逗号分隔的字符串进行存储,查询数据时使用 LIKE 方式匹配。作为 AB 实验报告查询的必查条件,这种查询方式无疑是低效的。
我们希望的聚合方式如下图所示:
我们需要将字段拆开,把数据打平,使用精确匹配来取代LIKE查询,提高查询的效率。
控制聚合表数据量
如果只做拆分打平的处理必然会导致数据量的激增,未必能达到正向优化的效果,因此我们还需要想办法来压缩打平后的数据量:
- 聚合表选取维度字段建模的时候,除了上文提到的,以字段的使用频次热度作为依据之外,也要关注字段的取值基数,进行综合取舍。如果取值基数过高的维度字段进入聚合表,必然会对控制聚合表的数据量造成阻碍。因此,我们在保证聚合表请求覆盖量的前提下,酌情舍弃部分高基数(取值有十万种以上)的维度。
- 从业务的角度尽可能过滤无效数据(比如一个实验组的流量为 0% 或者 100%,业务上就没有对照的意义,用户也不会去查,这样的数据就不需要进入聚合表)。
经过这一系列步骤,最终聚合表的数据量被控制在单日约 8000 万条,并没有因为 打平而膨胀。
值得一提的是,字段拆分后,除了查询从LIKE匹配变为精确匹配,还额外带来了两项收益:
- 字段从类型变为类型,作为查询条件时的比对效率变高。
- 能利用Doris的前缀索引和布隆过滤器等能力,进一步提高查询效率。
使用 BITMAP 去重代替 COUNT DISTINCT
要提速实验报告查询,针对进组人数(去重用户数)的优化是非常重要的一个部分。作为一个对明细数据强依赖的指标,我们如何在不丢失明细信息的前提下,实现像 Sum,Min,Max 等指标一样高效的预聚合计算呢?BITMAP 去重计算可以很好的满足我们的需求。
什么是BITMAP去重?
BITMAP 去重简单来说就是建立一种数据结构,表现形式为内存中连续的二进制位(bit),参与去重计算的每个素(必须为整型)都可以映射成这个数据结构的一个 bit 位的下标,如下图所示:
计算去重用户数时,数据以 的方式进行合并,以的方式得到结果。更重要的是,如此能实现去重用户数的预聚合。BITMAP 性能优势主要体现在两个方面:
- 空间紧凑:通过一个 bit 位是否置位表示一个数字是否存在,能节省大量空间。以 Int32 为例,传统的存储空间为 4 个字节,而在 BITMAP 计算时只需为其分配 1/8 字节(1个 bit 位)的空间。
- 计算高效:BITMAP 去重计算包括对给定下标的 bit 置位,统计 BITMAP 的置位个数,分别为 O(1) 和 O(n) 的操作,并且后者可使用 CLZ,CTZ 等指令高效计算。此外,BITMAP 去重在 Doris 等 MPP 执行引擎中还可以并行加速处理,每个节点各自计算本地子 BITMAP,而后进行合并。
当然,以上只是一个简化的介绍,这项技术发展至今已经做了很多优化实现,比如RoaringBitmap,感兴趣的同学可以看看:https://github.com/RoaringBitmap/RoaringBitmap
全局字典
要实现 BITMAP 去重计算,必须保证参与计算的素为 UInt32 / UInt64,而我们的为类型,因此我们还需设计维护一个全局字典,将映射为数字,从而实现 BITMAP 去重计算。
由于聚合数据目前只服务于离线查询,我们选择基于Hive表实现全局字典,其流程如下:
指标聚合
生成 Doris 聚合表时,将 作为查询指标以 BITMAP 类型来存储,其他常规查询指标则通过 COUNT/SUM/MAX/MIN 等方式聚合:
如此明细表和聚合表的指标计算对应关系如下:
优化效果
SQL视角
查询请求转换成 SQL 之后,在明细表和聚合表的表现对比如下:
- 常规聚合指标查询的性能提升自不必说(速度提升 50~60 倍)
- 进组人数查询性能的提升也非常可观(速度提升 10 倍左右)
集群视角
SQL 查询的快进快出,使查询占用的资源能快速释放,对集群压力的缓解也有正向的作用。
Doris 集群 BE 节点 CPU 使用情况和磁盘IO 状况的改变效果显著:
需要说明的是,集群状况的改善(包括实验报告查询 P95 提升)并不全归功于数据预聚合优化工作,这是各方合力协作(如产品业务形态调整,后端查询引擎排队优化,缓存调优,Doris 集群调优等)的综合结果。
小技巧
由于业务查询需求的多样,在查询明细表时,会出现一个字段既作为维度又作为指标来使用的情况。
如广告业务表中的(目标转化个数)字段,此字段的取值为 0 和 1,查询场景如下:
如果这个字段被选取进入聚合表,应该如何处理呢?
我们的处理方式是:
- 在聚合表中把这类字段建模成维度
- 聚合表中需要一个计数指标 cnt,表示聚合表中一条数据由明细表多少条数据聚合得
- 当这类字段被作为指标查询时,可将其与cnt指标配合计算得到正确结果
明细表查询:
结束语
经过这一系列基于 Doris 的性能优化和测试,A/B 实验场景查询性能的提升超过了我们的预期。值得一提的是,Doris 较高的稳定性和完备的监控、分析工具也为我们的优化工作提效不少。 希望本次分享可以给有需要的朋友提供一些参考。
最后,感谢 SelectDB 公司和 Apache Doris 社区对我们的鼎力支持。Apache Doris 是小米集团内部应用最为广泛的 OLAP 引擎之一,目前集团内部正在推进最新的向量化版本升级工作。未来一段时间我们将会把业务优化工作和 Doris 最新的向量化版本进行适配,进一步助力业务的正向发展。
— End —
最后,欢迎更多的开源技术爱好者加入 Apache Doris 社区,携手成长,共建社区生态。Apache Doris 社区当前已容纳了上万名开发者和使用者,承载了 30+ 交流社群,如果你也是 Apache Doris 的爱好者,扫码加入 Apache Doris 社区用户交流群,在这里你可以获得:
- 专业全职团队技术支持
- 直接和社区专家交流,获取免费且专业回复
- 认识不同行业的开发者,收获知识以及合作机会
- Apache Doris 最新版本优先体验权
- 获取一手干货和资讯以及活动优先参与权
Scheme-langserver 是基于 Chez Scheme 并兼容 scheme r6rs 的 language server protocol 实现。它最大的特点是基于未完成的代码做编程辅助,包括自动完成、定义跳转等。这些功能是基于对r6rs标准的scheme进行静态分析得到的。它被发布在Akku和github。
一些辅助功能如自动完成、定义跳转、鼠标悬停显示文档等功能对于编程十分有帮助。但是,和其他的编程语言如java、python、javascript和c,lisp系的语言服务器协议实现(language server protocol implementation)几乎是一篇空白。emacs的Geiser、Dr. Racket的racket langserver还有swish-lint等等,他们的工作基本上是基于repl(Read-Eval-Print Loop)或者词法解析器的,而不是基于编程的一般过程。例如,如果程序员正参与一个未完成的项目,里面的代码还并不是都能跑起来,Geiser或者其他的竞品都只能提供对顶级变量、标识符的自动补全,这些标识符在Chez Scheme里面一般都通过environment-symbols过程列出来。也就是说,对于未完成的代码和局部标识符、局部变量(在其他语言中自动完成功能主要就是在补全它们),Geiser等等无济于事。类似的事情同样出现在定义跳转等其他功能上。
一个根本的原因是,对于scheme和lisp的其他方言,它们丰富的数据结构和灵活的控制机制让代码的静态分析变成了一个很大的挑战。事实上,scheme甚至没有通用的项目管理框架及对应的文件扩展名。以.ss和.scm为例,大多数程序员假设使用这两个文件扩展名的代码被用于一个正在运行中的环境,并且并不明示代码所需要的库信息。虽然Akku和Snow鼓励通过.sls和.sld提供文件信息并建构一套稳定的库管理框架,但是involve、load和很多其他过程让库链接动态化,这就更不可能在代码静态分析阶段得到什么信息了。
John MacFarlane 是加州大学的哲学教授,也是一名程序员。他是文档工具 Pandoc 的作者,也是 CommonMark 标准的制定者之一。CommonMark 是强定义的 Markdown 规范,它会对很多细节做出定义,以避免歧义性。
近日,John MacFarlane 又发布了一种轻量的标记语法:Djot(发音:/dʒɑt/)。Djot 包含许多派生自 CommonMark 的功能,同时修复了一些使 CommonMark 语法复杂且难以有效解析的问题。
按照 John MacFarlane 的说法,Djot 属于 Markdown 的升级版,最初是为了实现他在 Beyond Markdown 中提出的一些想法。
据介绍,Djot 的功能比 CommonMark 更全面,支持定义列表、脚注、表格、几种新的内联格式(插入、删除、高亮、上标、下标)、数学、智能标点符号、可应用于任何的属性素,以及用于块级 (block-level)、内联级 (inline-level) 和原始内容 (raw content) 的通用容器。
在 Djot 的语法中,对硬换行的解析与常见的 Markdown 不同。
比如使用 Markdown 可以写成这样:
但在 Djot 中,如果使用了块级素,一定要采用硬换行:
对于列表也是同样的处理:
- Markdown
- Djot
Djot 的解释器采用解释性语言 Lua 编写,据称速度很快,可以生成 AST、渲染 HTML,以及语法高亮显示或 linting 工具。
Djot 语法说明:https://htmlpreview.github.io/?https://github.com/jgm/djot/blob/master/doc/syntax.html。
Mozilla 和微软已经对 TrustCor 的三个根证书采取了行动,这些根证书现在不再被 Firefox 和 Edge 浏览器所信任。
整个事情的起因可以追溯到今年年初 ,当时卡尔加里大学(University of Calgary)教授 Joel Reardon 在一系列总下载量超过 4600 万次的 Android 应用程序中发现了有收集用户数据的恶意行为。
调查发现,这些软件中的恶意代码都是由 Measurement Systems 开发的,他们的 SDK 包含这些恶意代码,而且 Measurement Systems 还与一家为美国政府从事网络情报和情报拦截工作的承包商之间存在联系。
进一步调查还发现,Measurement Systems 和 TrustCor 的域名都是由 Vostrom Holdings 所注册,注册时间仅相隔一个月;这两个公司实体都有相同的公司管理人员;TrustCor 运营的 Msgsafe “加密” 电子邮件服务,包含 Measurement Systems 的间谍软件 SDK,而且该服务实际上是以明文形式发送电子邮件,用户的电子邮件一览无余,与 “加密” 毫无关系。
虽然目前没有证据表明 TrustCor 作为一家根证书颁发机构(CA)有违反相应政策或程序的行为,也没有证据表明他们曾错误地颁发了受信任的证书,但调查结果使人们对 TrustCor 作为公众信任的 CA 运营的能力产生了合理怀疑。
Mozilla 项目经理 Kathleen Wilson 就表示:
对 TrustCor 的担忧已经得到证实,TrustCor 继续成为 Mozilla Root Program 成员的风险高于对最终用户的好处。
正因如此,目前 Mozilla 和微软都将 TrustCor 列入了不再信任的名单中,其中 Firefox 将不信任的日期设定为 2022 年 11 月 30 日,而微软将该日期设定为 2022 年 11 月 1 日。Google 的 Chrome 和苹果的 Safari 暂时没有采取任何行动,不确定他们会在何时跟进。
虽然 Chrome 和 Safari 暂时没有跟进,但用户可以在浏览器中手动删除或选择不信任 TrustCor 证书(上图以 Safari 浏览器为例)。
在今年 3 月份,JetBrains 曾宣布将无限期暂停在俄罗斯的销售和研发活动,以及无限期暂停在白俄罗斯的销售。现在,该公司又发布了有关该事件的最新更新公告。
公告内容指出,除了终止所有销售外,JetBrains 在俄罗斯的所有办事处,包括莫斯科、新西伯利亚和圣彼得堡都已被关闭,在圣彼得堡的新园区的工作也被终止。所有研发活动逐渐停止,其俄罗斯法人实体的清算文件也已于 2022 年 8 月提交。
JetBrains 俄罗斯团队共有 800 多人。目前该公司已设法将大部分员工从俄罗斯迁出,因个人原因无法搬迁的则已与公司分道扬镳。JetBrains 将这些迁出的人员分配到了在欧洲的办事处,包括在阿姆斯特丹、慕尼黑和柏林的研发中心。同时还在塞浦路斯、塞尔维亚和亚美尼亚开设了新据点。
该公司表示,鉴于客户的大力支持和公司整体良好的财务状况,其有能力继续开发优质的开发工具。并且还发布了一些职位招聘,涵盖 IntelliJ IDEA 团队的 UI/UX 设计师、软件工程师,以及 Kotlin IDE 的高级软件开发人员等等。
JetBrains 方面称,虽然这对公司来说是一个非常具有挑战性和困难的时期。但他们依然选择继续支持乌克兰,并重申了其对俄罗斯政府发起的袭击的谴责。
相关阅读:JetBrains:无限期暂停在俄罗斯的销售和研发活动
在解雇了大部分技术人员的同时,Twitter 新所有者兼首席执行官 Elon Musk 似乎也放弃了对其开源工作的支持。
与大多数现代软件公司一样,Twitter 依赖于开源程序;其基于 CentOS 7 运行,该版本将于 2024 年 6 月结束生命周期。因此,Twitter 方面原本的计划是迁移到 CentOS Stream。但鉴于目前的情况,Twitter 方面好像已经没剩下什么人来推进这个操作系统迁移了。
而 Twitter 对开源软件的依赖也远不止其基础操作系统。Twitter 前开源负责人 Will Norris 在接受 ZDNet 采访时表示,他曾与当时的 Twitter 首席执行官 Parag Agrawal 详细讨论过关于改进 Twitter 对关键开源项目的投资事项。
当我加入时,已经有许多大型的现代化工作正在进行中,其中包含大型开源组件。Pants 构建系统正在被 Bazel 取代,准备用 Kubernetes 取代 Apache Aurora 和 Mesos 的工作也正在进行中。而且,我们已经是 Apache Kafka、Hadoop 和 Scala 的最大用户之一。我们还有一个 JVM 的自定义分支,我们希望它最终能够开源。有很多令人惊叹的工作正在发生,他们成功地从这些社区聘请了非常优秀的人来从事这些项目。
然后今年发生了这些变故 :-
首先,马斯克开始时断时续地收购 Twitter。因此在看到一条明确的前进道路前,Twitter 高管选择冻结了其开源计划和投资;但最终,马斯克解雇了所有高管。 很快,大多数开发人员也被解雇。如今,Twitter 一半以上的员工要么被赶走,要么跳槽。
Norris 指出,“大多数在 Twitter 从事开源工作的关键人物都离开了。所有与我一起从事开源工作的工程师都离开了”。他认为,这对 Twitter 意味着:
短期内,可能不会有太多开源工作计划。对于 Twitter 来说,变回仅仅作为开源的消费者而不做出任何有意义的贡献是相对容易的;反正很多公司都是这么做的,他们可以像以前一样继续使用 CentOS、Scala、Kafka 和其他所有软件。对于处于迁移过程中的项目,例如 Bazel 和 Kubernetes,停止可能会更痛苦,但这取决于事情处于什么状态。我不得不想象所有的重点只是保持服务运行和添加 Musk 想要的任何产品改变。
Twitter 的现任员工透露,他们目前所能做的就是“keep the wheels turning”。并表示,Twitter 每月 8 美的蓝 V 认证服务延迟推出的真正原因不仅仅是因为被冒名账号所滥用,而是因为开发人员还无法自动化阻止此类滥用行为。
从长远来看,Norris 认为 Twitter 在开源社区中已经变得无关紧要。“他们已经失去了作为一个严肃的工程组织的所有信誉,我不在乎你如何称自己为’hardcore’。开源社区建立在关系和信任的基础上,而现在 Twitter 与这些团体没有任何关系。他们已经失去了任何有意义地参与这些社区的能力。”
但是,有一个迫在眉睫的问题是:Twitter 自己的开源项目。Norris 表示:
它们中的许多不再被积极维护(这是它自己的问题),但它们非常流行,尤其是在 Scala 世界(Finagle、Twemoji、Scalding 和 Algebird)。Twitter 有适当的流程来维持其中一些开源项目(如 Finagle)与代码的内部副本保持同步,但这些都不是完全自动化的。我非常怀疑是否有人留下来做这项工作。那么这些项目的外部用户 (包括 ING Bank、Pinterest 和 SoundCloud 等公司)会怎样呢?
此外,Norris 指出,https://github.com/twitter 中的项目维护将会变得很奇怪。因为 Twitter 有一个内部系统来管理它在 GitHub 上的存在。它允许 Twitter 员工注册自己的 GitHub 帐户来访问他们的 Twitter 开源项目。过去的情况是,当某人离开公司时他们的访问权限会被留下,但他们会从 GitHub 上的 Twitter 组织的成员转为外部合作者。
然而即使在马斯克接手之前,Twitter 有时也没能让离开公司的开发人员很好的剥离权限。在 2022 年 8 月,一名员工在离开公司 18 个月后就仍能访问 Twitter 的 GitHub 和源代码。Twitter 在今年早些时候对这一问题进行了修复,但相关工作并未正式完成。因此,Norris 称,“一些维护人员已经在多年前离开了 Twitter 的项目,可能仍然有感兴趣的人在继续访问。”
当然,那些最近被解雇或辞职的人以及“最了解剩余活跃项目的人,几乎可以肯定已经被删除了他们的访问权限” 。几个月前甚至几年前的 Twitter 前员工则很可能仍然拥有代码访问权限,而那些知道谁应该拥有代码访问权限的、但在最近已经被解雇了的员工将不再负责解决问题。
至于 Twitter 自己的开源项目 (如 Finagle),Norris 预计 Twitter 不会做任何事情来继续维护这些项目,至少不会达到以前的水平。因此,从现实的角度来看,所有这些项目可能都需要分叉并转移到一个新的地方,但这将是一个混乱的过程,而且可能会有很大的破坏性。
11 月 27 日,知名前端框架 Vue 的周 npm 下载量激增十倍,以至于 Vue 创始人尤雨溪发推求助“我也不知道谁搞出来的,请你赶紧修复吧。”
从 NPM Trends 页面上可以看到,上上周 (11 月 27 日)的 vue npm 下载量达到惊人的 3800 万,比前一周(11 月 20 日 )的 360 万下载量暴增了十倍。而其他前端框架,如 React 和 angular 都没有明显的波动。
反而是另一款前端 UI 框架 Svelte 也经历了过山车式的体验,周下载量先是从日常 40 万飙升到 2800 万,然后又狠狠地下跌,但仍未恢复至正常水平。
热心网友建议尤雨溪直接问 npm 官方,但是 Svelte 框架作者 Rich Harris 表示他已经尝试过和 npm 方面沟通,然而 npm 官方无法透露任何有用的信息,目前只知道 UA 来自 Deno,其他情况一概不知 。
大伙纷纷在尤雨溪的推文下面评论调侃,猜测 Npm 下载量暴涨的原因:Vue 框架贡献者 Johnson Chu 称这也许是一项行为艺术,以此来表达通过下载量来比较前端框架毫无意义。
又有网友认为也许是最近火热的 chatGPT AI 正在大量学习如何制作 Vue 应用程序,在每次迭代中都会运行 npm install,导致下载量暴增。此外,也有人认为该事件与 Nuxt 框架 3.0 版本的正式发布有关,Nuxt 3.0 版本基于 Vue 3 构建,可能会导致 Vue 的下载量暴增。
但导致 Vue npm 下载量暴增的原因尚未有明确的定论,只能等下一轮 npm 统计数据或者官方公告,我们会密切跟踪后续发展。
摘要:糟糕,数据库异常不可用怎么办?挺着急的,在线等。
本文分享自华为云社区《糟糕,数据库异常不可用怎么办?》,作者:GaussDB 数据库。
随着数字化转型的加速,数据量爆发式增长,用户对数据库运维能力要求更高,实现对数据库的高效智能管理,尤其是业务异常时,数据库运维平台能自动定位故障并修复,或者提供有价值信息,帮助客户快速定位解决问题。
华为云数据库团队打造的RDS for MySQL智能DBA助手,为数据库管理人员提供了一站式数据库运维方案,能够帮助用户快速处理异常,保持业务稳定运行。近期,我们新上线了自治限流功能,通过限流非核心业务SQL来保障核心业务稳定运行,下面将为您带来该项业界领先的功能的详细解读。
在遭遇异常流量高峰时,如何处理?
在实际运维场景中,客户因为业务变更或者业务高峰期会带来流量高峰,导致系统指标异常,实例CPU飙升近100%,会话SQL处理变慢,活跃连接数增加,数据库响应异常甚至不可用。可能的原因有以下两个方面:
- SQL问题:SQL执行效率慢,如对无主键、无索引的表进行查询操作时,CPU和 IO被打满。
- 流量问题:突发的流量急剧上升,数据库容量达到瓶颈,影响正常业务。
解决方案:
针对上述问题,一般会采用两种方式来处理:
方式一:先分析异常SQL,定位后手动Kill会话
方式二:简单粗暴,重启数据库。
但面对复杂问题,传统解决方案往往无法从根本上解决,定位解决问题花费时间长,导致业务受损。针对这一挑战,业界采用限流的方式来处理,不区分业务,即不会区分限流SQL所在的库或者客户端用户,这可能导致无差别的kill会话,核心业务受损。
我们今天介绍的自治限流功能是如何应对这一潜在风险呢?
自治限流,指的是通过预先设置限流策略,自动限定执行SQL的并发度,通过小部分业务受损,保障核心业务的正常运行。具体来说,可以通过以下三个策略来进行流控:
分库、分用户设置限流范围
自治限流功能支持分库、分用户两种方式设置,客户根据业务情况,识别核心业务库和客户端用户,按需选择相应的限流方式。
- 按库设置:根据业务重要程度,选择对特定的一个或者多个库进行限流,默认不区分库名。
- 按用户名设置:根据不同用户业务差异,选择对特定的一个或者多个用户进行限流,默认不区分用户。
设置限流时间:
通过设置限流时间窗(即自治限流功能只在该时间段生效)和每次最大限流时长(即自治限流生效后持续时长),方便定位SQL异常,请注意:同一天只在该时间窗内生效一次。
设置限流策略
条件1:根据业务情况,设置CPU利用率大于多少 【且/或】 活跃会话数大于多少,且上述条件持续时间大于多少分钟,会触发限流。
条件2:设置允许的最大活跃并发数,当前活跃会话数大于最大活跃会话数时,会将会话数清理到小于最大活跃会话数。
设置界面如下:
完成上述设置后,自治限流功能可以自动检测客户实例异常,触发限流策略后,根据配置的限流范围和时间,自动进行分库分用户限流处理,在保证核心业务SQL稳定运行的前提下,限制引发CPU飙升的新上业务SQL,带来活跃会话数逐渐降低,CPU下降到正常值,QPS恢复到业务正常水平,数据库实例恢复正常。
流量高峰常常是不可预测的,这给运维带来非常大的挑战和工作负担。华为云数据库自治限流功能,通过分库与分用户限流方式,自动检测数据库异常,并及时进行限流处理,保障核心业务的稳定运行,极大减轻了DBA的运维压力,使其更聚焦数据架构设计以及数据价值挖掘等核心工作。目前该功能已上线,欢迎大家体验。https://www.huaweicloud.com/product/mysql.html
关注,第一时间了解华为云新鲜技术~
摘要:华为云Solution as Code推出基于Ploto构建自动驾驶平台解决方案。
本文分享自华为云社区《基于Ploto构建自动驾驶平台》,作者:阿米托福 。
2022年6月15日,主题为“因聚而生 为你所能”的华为伙伴暨开发者大会 2022 正式开启,在自动驾驶专场中,华为云携手合作伙伴联合发布“乐高式”自动驾驶研发平台解决方案,实现自动驾驶研发效率提升。
联合发布“乐高式”自动驾驶研发平台解决方案
一、自动驾驶商业化落地加速,研发业务面临 4 大挑战
近几年,自动驾驶行业整体加速发展,一线城市开放道路达到1600公里+,二三线也在逐步开放,牌照发放数量持续增长年增长600张+,得益于开放道路和牌照的大幅度增长,2022年中国路测里程达到2000万公里以上,当前国内车企研发的L3/L4自动驾驶技术,单车数据可达60TB/天,因此,自动驾驶的发展对数据和算力的需求成倍增加。
自动驾驶对数据和算例的需求主要体现在 4 个方面:海量数据管理难、成本高;算法训练计算资源需求大;数据处理业务流程复杂,新技术门槛高;全流程的数据合规要求高。
华为云自动驾驶业务研发平台业务全景图
二、基于Ploto构建自动驾驶平台
华为云Solution as Code重磅推出基于Ploto构建自动驾驶平台解决方案,该解决方案基于华为云开源项目Ploto构建,集合业界优秀伙伴提供的专业自动驾驶研发工具,打造“乐高式”解决方案,具有模块化架构体系,为自动驾驶全链路提供可靠服务(数据采集、数据传输、数据脱敏、场景数据提取、数据标注、AI训练、仿真测试、评估评价、OTA升级全链路流程)。
基于Ploto构建自动驾驶平台一键部署
基于这种灵活部署的架构和接口,客户在各个环节都能自主选择业界最契合自己业务发展的伙伴;同时本着激活自动驾驶生态圈、促进自动驾驶行业发展的目标,华为云欢迎更多的专业软件服务商加入共建生态,推动自动驾驶产业的革新。
自动驾驶研发平台 Ploto 数据大屏
在实际业务中,“乐高式”自动驾驶研发平台解决方案聚焦“路测数据上云、算法训练及场景仿真”等 3 类自动驾驶典型场景。通过华为云与伙伴共建 POP 点、提供专属 CPU 资源池、优化仿真环节等工作,帮助客户大幅节省存储成本,算法训练效率显著提升,实现降本增效。
三、乐高式、开放化——高效构建自动驾驶研发平台的行业新解
华为云汽车行业解决方案负责人赵刚谈到:华为云坚持“生态开放”的理念,深度联合禾多科技、51WORLD、星尘数据、易图通等合作伙伴,共同发布“乐高式”自动驾驶研发平台解决方案(以下简称“乐高式”解决方案),帮助客户最快 2 周即可独立完成一套自动驾驶研发平台的搭建。
本次发布的解决方案依托华为云丰富的云服务及生态伙伴在自动驾驶领域的经验沉淀,赋能客户打通数据闭环流程,并联合伙伴在全国建设数据接入点,传输效率最高提升 3 倍、实现当日上云;软硬件协同优化,多机多卡训练效率提升 50%;支持云原生集群化部署,调度性能提升 30%;支持数据加密、合规治理,保障业务安全合规。
华为云自动驾驶业务研发平台以开源代码库 Ploto 为门户,由安全合规、路测数据管理、AI 算法训练、场景仿真、场景库交易、量产车联网及平台管理等 7 个模块组成,支持 3 种业务部署模式。华为云及伙伴们希望通过“乐高式、模块化”的简单操作,来帮助不同诉求的客户实现自动驾驶研发平台快速构建的目标。
模式 1:模块按需构建
“乐高式”解决方案自身具备“按需搭建,灵活组合”的能力,适用于对部分研发模块有诉求的客户,最少只需 9 个标准 API 便可快速与自有研发平台对接上云。
模式 2:E2E 快速构建
对于有端到端构建研发平台诉求的客户,“乐高式”解决方案提供一站式的服务,帮助用户基于参考代码快速构建。
模式 3:自有专业软件服务商集成
相比 SaaS 化自动驾驶研发平台,华为云提供标准 API,支持客户自选如标注、仿真等环节的专业软件服务商快速集成。
目前《基于Ploto构建自动驾驶平台 》已上线华为云官网,快来体验吧!
关注,第一时间了解华为云新鲜技术~
摘要:MindStudio提供精度比对功能,支持Vector比对能力。
本文分享自华为云社区《【MindStudio训练营第一季】MindStudio 高精度对比随笔》,作者:Tianyi_Li。
训练场景下,迁移原始网络 (如TensorFlow、PyTorch) ,用于NPU上执行训练,网络迁移可能会造成自有实现的算子运算结果与用原生标准算子运算结果存在偏差。推理场景下, ATC模型转换过程对模型进行优化,包括算子消除、算子融合算子拆分,这些优化也可能会造成自有实现的算子运算结果与原生标准算子(如TensorFlow、ONNX、 Caffe ) 运算结果存在偏差。
为了帮助开发人员快速解决算子精度问题,需要提供自有实现的算子运算结果与业界标准算子运算结果之间进行精度差异对比的工具。
对策:
精度比对工具能够帮助开发人员定位本次任务两个网络间的精度差异。准备好昇腾腾AI处理器运行生成的dump教据与Ground Truth数据 (基于GPU/CPU运行生成的数据)后,即可进行不同算法评价指标的数据比对。
MindStudio提供精度比对功能,支持Vector比对能力,支持下列算法:
- 余弦相似度
- 最大绝对误差
- 累积相对误差
- 欧氏相对距离
- KL散度…
精度比对根据推理/训练和不同的框架分为多个比对场景。
原始模型数据即为原始网络在GPU/CPU侧生成的数据,主要依赖原始框架中的源生能力,将模型中每一个算子节点的输入输出数据进行保存。
NPU模型数据即为通过对原始模型的迁移或训练在县腾A处理器上得到的数据,主要依赖华为侧提供对应用推理及训练提供的Dump能力,将模型中每一个算子节点的输入输出数据进行保存。
由于MindStudio精度比对工具的使用约束,数据需要满足以下格式:
原始模型数据准备
以TensorFlow为例
在进行TensorFlow模型生成npy数据前,您需要已经有一套完整的、可执行的、标准的TensorFlow模型应用工程。然后利用TensorFlow官方提供的debug工具tfdbg调试程序,从而生成npy文件。通常情况下,TensorFlow的网络实现方式主要分为Estimator模式和session.run模式,具体操作如下:
1.修改tf训练脚本,添加debug选项设置
2.执行推理或训练脚本,任务运行到前面debug配置后暂停
3.进入调试命令行交互模式后,
- 3.1 输入run命令,训练会往下执行一个step
- 3.2 执行lt >tensor name将所有tensor的名称暂存到文件里,在另一个窗口,在Linux命令下执行下述命令,用以生成在tfdbg命令行执行的命令:
- 3.3 将上一步生成的tensor name cmd.txt文件内容粘贴执行,即可存储所有npy文件,实现训练数据的Dump。
注: 更加详细操作见《CANN开发辅助工具指南》中“精度比对工具使用指南”章节。
NPU模型数据准备
以推理场景为例
推理场景数据准备一NPU的融合后推理数据NPU采用AscendCL完成离线推理:
1.在代码中调用acllnit(“https://www.xujun.org/acl.json”)
acl.json的文件内容如下:
2.运行推理应用,生成dump数据
以训练场景为例
训练场景数据准备-NPU的迁移后网络训练数据
以TensorFlow为例,步骤如下:
1.设置“DUMP GE GRAPH=2”生成计算图文件,同时修改训练脚本,开启dump功能
2.执行训练脚本,生成dump数据和计算图文件
- 计算图文件:“ge”开头的文件,存储在训练脚本所在目录
- dump数据文件: 生成在dump path指定的目录下,即(dump path)/time)/(deviceid)/(model name)/(model id)/(data index) 。
3.选取计算图文件
可使用grep lterator* Build.txt命令快速查找出的计算图文件名称,如ge proto 00005 Build.txt.
4.选取dump数据文件
打开上述计算图文件,找出第一个graph中的name字段,即为dump文件存放目录名称。
精度对比工具使用方法
创建对比任务
将准备好的标准数据文件与待比对数据文性作为输入文件,并配置对应的离线模型文件,通过对文件内所有参与计算的算子输入与输出进行精度比对。
整网比对在MindStudio界面菜单栏洗择“Ascend > Model Accuracy Analvzer > New Task菜单,进入比对界面。
整网对比结果
整网比对结果主要分为四大展示模块:
- 整网对比结果表;
- 精度散点图;
- 模型可视化:
- 精度专家建议
精度比对工具本身只提供自有实现算子在昇腾AI处理器上的运算结果与业界标准算子的运算结果的差异比对功能,而输出的比对结果需要用户自行分析并找出问题。而对结果的分析工作对于用户来说也是一大难点,而专家系统工具为用户提供精度比对结果的结果分析功能,有效减少用户排查问题的时间。只需在比对操作配置任务时勾选“Advisor”选项,系统则会在比对完成后自动进行结果文件的分析,并输出优化建议。
当前支持的分析检测类型有:FP16溢出检测、输入不一致检测、整网一致性检测(整网一致性检测包括:问题节点检测、单点误差检测和一致性检测三个小点)
这里特别说明下FP16溢出检测,针对比对数据中数据类型为FP16的数据,进行溢出检测。如果存在溢出数据,输出专家建议,示例图如下所示。
单算子对比
可针对整网任务中的某个算子进行单算子比对,分析某个算子的具体精度差异。
使用约束
- 精度比对功能不支持打开多个工程同时进行比对,可以先完成一个比对程序后再进行下一个。
- 精度比对支持的dump数据的类型:
特别说明
dump文件无法通过文本工具直接查看其内容,为了查看dump文件内容,需要用脚本将dump文件转换为numpy格式文件后,再通过numpy官方提供的能力转为txt文档进行查看。脚本在/home/HwHiAiUser/Ascend/ascend-toolkit/latest/tools/operator_cmp/compare目录,名为msaccucmp.py。举例用法如下:
调用Python,转换numpy文件为txt文件的完整示例如下:
但转换为.txt格式文件后,维度信息、Dtype均不存在。详细的使用方法请参考numpy官网介绍。
总结
精度对比总计分为环境准备、数据准备和对比三步。
数据准备要根据推理场景和训练场景分别分析:
- 推理场景:准备第三方框架原始模型的npy数据文件与离线模型的dump数据文件。
- 训练场景:准备基于GPU运行生成的第三方框架原始训练网络npy数据文件与基于昇腾AI处理器运行生成的训练网络dump数据和计算图文件。
准备后上述步骤,可进行对比:
- 执行整网比对操作。
- 开启MindStudio的“Ascend > Model Accuracy Analyzer”功能,将准备好的比对数据文件配置到对应参数下并配置具体比对参数。
- MindStudio执行比对操作并输出比对结果。
- 比对结果专家建议(可选)。请参见比对结果专家建议。
- 根据分析结果定位具体问题算子。
- 执行单算子比对操作。
- 分析单算子具体问题。
最后说下Tensor比对,Tensor对比提供整网比对和单算子比对两种精度比对方式,需要根据比对场景选择比对方式。其中,整网比对:将准备好的标准数据文件与待比对数据文件作为输入文件,通过对文件内所有参与计算的算子进行精度比对。而单算子比对:在整网比对的基础上指定具体算子名,对单个算子进行详细数据的比对。
个人认为,精度对比这是一个需要时间、精力和经验的操作,要充分利用好MindStudio工具,或查文档,或提问,可大大降低我们的工作量,提高效率。但是不得不说,这是需要一定经验的,还是要多看多学习,多试多问啊。
关注,第一时间了解华为云新鲜技术~
前言
链路追踪是每个微服务架构下必备的利器,go-zero 当然早已经为我们考虑好了,只需要在配置中添加配置即可使用。
关于 go-zero 如何追踪的原理追溯,之前已经有同学分享,这里我就不再多说,如果有想了解的同学去 https://sigusoft.com/s/hJEWcWc3PnGfWfbPCHfM9g 这个链接看就好了。默认会在 api 的中间件与 rpc 的 interceptor 添加追踪,如果有不了解 go-zero 默认如何使用默认的链路追踪的,请移步我的开源项目 go-zero-looklook 文档 https://github.com/Mikaelemmmm/go-zero-looklook/blob/main/doc/chinese/12-%E9%93%BE%E8%B7%AF%E8%BF%BD%E8%B8%AA.md。
今天我想讲的是,除了 go-zero 默认在 api 的 middleware 与 rpc 的 interceptor 中帮我们集成好的链路追踪,我们想自己在某些本地方法添加链路追踪代码或者我们想在 api 发送一个消息给 mq 服务时候想把整个链路包含 mq 的 producer、consumer 穿起来,在 go-zero 中该如何做。
场景
我们先简单讲一下我们的小 demo 的场景,一个请求进来调用 api 的 方法,在 Login 方法中先调用 rpc 的 方法,之后在调用 api 本地的 方法,紧接着调用 传递消息到 mq 服务。
go-zero 默认集成了 jaeger、zinpink,这里我们就以 jaeger 为例
我们希望看到的链路是
也就是 api 衍生出来三条子链路, 有一条调用 的子链路。
我们想要将一个方法添加到链路中需要两个因素,一个 traceId,一个span,当我们在同一个 traceId 下开启 span 把相关的 span 都串联起来,如果想形成父子关系,就要把 span 之间相互串联起来,因为「微服务实践」公众号中讲解原理太多,我这里就简单提一下不涉及过多,如果不是特别熟悉原理可以看文章开头推荐的文章,这里我们只需要知道 与 关系就好。
核心业务代码
1、首先 API 中 代码
2、rpc 中 的代码
3、mq 中 的代码
代码详解
1、go-zero 默认集成
当一个请求进入 api 后,我们可以在 go-zero 源码中查看到 https://github.com/zeromicro/go-zero/blob/master/rest/engine.go#L92。go-zero 已经在 api 的 middleware 中帮我们添加了第一层 trace,当进入 Login 方法内,我们调用了 rpc 的 方法,通过 go-zero 的源码 https://github.com/zeromicro/go-zero/blob/master/zrpc/internal/rpcserver.go#L55 可以看到在 rpc 的 interceptor 也默认帮我们添加好了,这两层都是 go-zero 默认帮我们做好的。
2、本地方法
当调用完 rpc 的 之后,api 调用了本地的 ,如果我们想在整个链路上体现出来调用了本地 方法,那默认的 go-zero 是没有帮我们做的,需要我们手动来添加。
我们通过上面代码拿到 tracer,ctx 之后开启一个 local 的 span,因为 start 时候会从 ctx 获取父 span 所以会将 local 方法与 Login 串联起父子调用关系,这样就将本次操作加入了这个链路
3、mq 的 producer 到 mq 的 consumer
我们在mq传递中如何串联起来这个链路呢?也就是形成 。
想一下原理,虽然跨越了网络,api 可以通过 传递,rpc 可以通过 传递,那么 mq 是不是也可以通过 、 传递就可以了,按照这个想法来看下我门的代码。
首先获取到了这个全局的 ,然后开启一个 的 ,跟 方法一样,我们开启 的 时候也是通过 获取到上一级父级 ,这样就可以将 的 与 形成父子 调用关系,那我们想将 的 与 mq 的 中的 形成调用父子关系怎么做?我们将 的 注入到 中,这里我们通过 mq 的 将 发送给 ,发送完成我们 我们的 ,那么 的这层链路完成了。
随后我们来看 在接收到 消息之后怎么做的。
接收到消息后反序列化出来 ,然后通过 取出来 注入的 ,在通过 、 创建 的 ,这样 就是 的子 ,就形成了调用链路关系,最终我们得到的关系就是
让我们来调用一下 方法,看下 jaeger 中的链路如果与我们预想的链路一致,so happy~
项目地址
go-zero 微服务框架:https://github.com/zeromicro/go-zero
https://gitee.com/kevwan/go-zero
go-zero 微服务最佳实践项目:https://github.com/Mikaelemmmm/go-zero-looklook
欢迎使用 并 star 支持我们!
微信交流群
关注『微服务实践』公众号并 交流群 获取社区群二维码。
一
在Java的平台里,其实是可以执行其他的语言的。包括且不仅限于jvm发展出来的语言。
有的同学可能会说,在java项目里执行其他语言,这不吃饱了撑着么,java体系那么庞大,各种工具一应俱全,放着好好的java不写,还要去执行其他语言干嘛。
写java的都知道,java是需要事先编译的,这意味着你很难去在运行中改变编译好的class信息,除非你用字节码等技术栈,但是这也是需要很大的成本的。要想在运行中很方便的改变业务逻辑,其实用java去执行其他的脚本语言是一个好办法。况且有的脚本语言有着比java更简洁的语法特性。
有兴趣的小伙伴也可以看看之前的这篇文章:Java 项目有可能做到所有的代码逻辑均可热部署吗?
二
在java中执行其他语言,可能你会觉得这应该很复杂,需要去学习每种语言包相关的api。
笔者是开源框架LiteFlow的作者,在规则引擎LiteFlow中实践并支持了许多的其他语言,如groovy,js,python,lua等。
我可以负责任的说,在Java平台中调用其他脚本语言,其实一点都不复杂,你无需关心每种语言的实际api。
这一切都归功于一个规范:。
相信有大部分人没听过这个Java平台的规范。
JSR223规范最初在Java6平台被提出,提供了一套标准的API为脚本语言的执行提供了内置支持。
也就是说,你只要熟悉这一套API就能执行大部分的脚本语言。
而且这套API的使用也是非常方便的,几个核心方法仔细看个10分钟就能明白如何使用。
三
来个最简单的例子:
上述代码演示的是用JSR223 API去执行javascript语言。值得一提的是,java内置了javascript引擎,你无需引入任何第三方包依赖就可以获得这个引擎。
整个过程分4块,分别是获得引擎,脚本编译,绑定java参数,执行。
在实际业务中,建议在系统启动的时候去编译脚本,然后把编译好的脚本对象 对象给缓存起来,因为编译过程相对比较耗时,运行时每次去编译是个糟糕的设计。
如果在运行中改变了脚本,只需要重新去编译这个脚本并缓存其编译后的对象即可。
你只需要掌握以上代码,那几乎就已经掌握了JSR223规范的使用了。是不是很简单?
四
如果你想换成groovy脚本语言,那你需要依赖第三方依赖
然后在上述的代码里获得引擎这块换成groovy即可:
如果你想换成python,需要依赖第三方依赖
然后在上述的代码里获得引擎这块换成python即可:
看到这,是不是对利用规范如何执行脚本恍然大悟了呢。
五
其实现在很多的语言在java平台都推出了自己的java三方执行依赖包,而且很多的包都支持了JSR223规范。只要支持了JSR223规范的语言,都可以利用上述的代码来执行。
JSR223规范的API可以支持java和其他语言的绑定和互通,一个java对象通过bindings对象也是可以传到脚本语言中的,在脚本语言中,你可以获得java的对象,来进行调用其方法和进行逻辑计算。
不过不同的语言调用操作符也许有所不同,比如groovy,javascript都是通过点操作符,和java很像,笔者在LiteFlow里新支持了Lua脚本,Lua脚本的对java对象的操作符是冒号。所以当你的项目支持相关的脚本语言之前,你先要熟悉下相关语言的语法。
六
用脚本语言来担当java平台中经常需要变动的部分是一个不错的选择。关键原因是脚本语言的编译,执行完全是动态的,这意味着你可以在java运行中改变脚本,重新编译,并执行。利用此特性来进行变相的热部署。
LiteFlow就是这样一款能够让你用多种脚本语言来定义你逻辑的规则引擎框架,这其中也利用了JSR223的规范API,不仅能用脚本来编写逻辑,还能进行规则编排。
项目官网:
https://liteflow.yomahub.com
gitee托管仓库:
https://gitee.com/dromara/liteFlow
希望大家都能从JSR223规范中找到一些设计你们相关业务系统的灵感。
作者:京东云质量部
背景
随着前端技术发展,已经转变为数据绑定为主流的框架方式,与后端服务一样,前端代码实现也会涉及相互依赖,引用这些场景,那么应该如何准确的评估前端代码改动的影响范围?依赖开发评估?依靠经验评估?或者直接前端自动化全回归?手工测试全回归?显然以上的策略都不是最优策略,本文叙述了通过对前端代码进行静态分析,找到改动文件影响的功能范围,从实现了一种前端精准测试的思路。
如何进行精准分析
前端对外可直接感知的就是页面,最终目标是要确定影响哪个功能。整个前端精准测试划分为4步:
第一步,确定影响的页面。
第二步,确定影响的功能。
第三步,根据分析结果,找到对应的自动化用例集合,并触发运行
第四步,对比前端代码增量覆盖率,确认改动覆盖完成
前端页面与路由直接相关,从路由入手,建立路由与展示页面的关系,再依据入口文件的import关系,建立前端代码文件依赖树,再通过git diff对比找到改动的文件,从而反查到影响的前端页面。
精准分析实现
设计思路
解析路由文件,建立路由文件中每个菜单的依赖树,从而根据改动文件反查影响页面
实现逻辑
鉴于上述设计思路,结合目前技术支撑现状及快速实验的目标,开发了前端精准分析的第一版方案。
(路由文件分析暂时未找到规律,且实际场景中,路由文件变更不会频繁,维护成本不高,所以此步骤暂由人工维护)
关键逻辑:文件依赖树的分析及存储
应用
webhook自动触发分析
在代码平台上配置webhook触发分析接口,即可实现代码提交,自动触发分析
平台手动触发分析
规划
目前平台仅仅实现了前端精准测试4步中第一步的80%(路由与入口文件的关联还未实现自动分析),推荐仅仅到了页面级别,还未达到按钮级别,此处还需要再研究一下前端开发的相关技术,找到自动解析路由的方法。第二步计划尝试借助istanbul前端覆盖率工具,做一下增量覆盖率对比,保证手动回归可覆盖改动。
作者:李玉亮
引言
数据库事务与大多数后端软件开发人员的工作密不可分,本文从事务理论、事务技术、事务实践等方面对常用的相关事务知识进行整理总结,供大家参考。
事务理论介绍
事务定义
在数据库管理系统中,事务是单个逻辑或工作单,有时由多个操作组成,在数据库中以一致模式完成的逻辑处理称为事务。一个例子是从一个银行账户转账到另一个账户:完整的交易需要减去从一个账户转账的金额,然后将相同的金额添加到另一个账户。
事务特性
原子性( atomicty)
事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
一致性(consistency)
事务的执行不能破坏数据库数据的完整性和一致性。一致性指数据满足所有数据库的条件,比如字段约束、外键约束、触发器等,事务从一致性开始,以一致性结束。
隔离性( isolation)
事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务是透明的。
持久性(durability)
对于提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。
注:DBMS一般采用日志来保证事务的原子性、一致性和持久性。
事务隔离级别
并发事务带来的问题
不可重复读的重点是数据修改场景,幻读的重点在于新增或者删除场景。
事务隔离级别
SQL92标准定义了4种隔离级别的事务
大多数数据库系统如oracle的默认隔离级别都是 Read committed,mysql默认为可重复读,InnoDB 和 XtraDB 存储引擎通过多版并发控制(MVCC,Multivesion Concurrency Control)解决了幻读问题,Repeatable read 是 Mysql 默认的事务隔离级别,其中 InnoDB主 要通过使用 MVVC 获得高并发,使用一种被称为 next-key-locking 的策略来避免幻读。
事务模型
事务提交模型
显式事务:又称自定义事务,是指用显式的方式定义其开始和结束的事务,当使用start transaction和 commit语句时表示发生显式事务。
隐式事务:隐式事务是指每一条数据操作语句都自动地成为一个事务,事务的开始是隐式的,事务的结束有明确的标记。即当用户进行数据操作时,系统自动开启一个事务,事务的结束则需手动调用 commit或 rollback语句来结束当前事务,在当前事务结束后又自动开启一个新事务。
自动事务:自动事务是指能够自动开启事务并且能够自动结束事务。在事务执行过程中,如果没有出现异常,事务则自动提交;当执行过程产生错误时,则事务自动回滚;一条SQL语句一个事务。
事务编程模型
本地事务模型:事务由本地资源管理器来管理。简单理解就是直接使用JDBC的事务API。
编程式事务模型:事务通过JTA以及底层的JTS实现来管理,对于开发人员而言,管理的是“事务”,而非“连接”。简单理解就是使用事务的API写代码控制事务。
示例一、JTA的API编程
示例二、Spring的事务模版
声明式事务:事务由容器进行管理,对于开发人员而言,几乎不管理事务。简单理解就是加个事务注解或做个AOP切面。
比较
附:SQL相关小知识
SQL的全称:Structured Query Language。中文翻译:结构化查询语言。
关系数据库理论之父:埃德加·科德。是一位计算机的大牛,他凭借关系数据模型理论获得了图灵奖,核心思想就两个:关系代数和关系演算,发表了一篇牛逼的论文“A Relational Model of Data for Large Shared Data Banks”。
写第一句SQL的人:Donald D. Chamberlin 和 Raymond F. Boyce。埃德加·科德的两个同事Donald D. Chamberlin和Raymond F. Boyce根据论文,发明出了简单好用的SQL语言。
SQL 标准:有两个主要的标准,分别是 SQL92 和 SQL99 。92 和 99 代表了标准提出的时间。除了 SQL92 和 SQL99 以外,还存在 SQL-86、SQL-89、SQL:2003、SQL:2008、SQL:2011 和 SQL:2016 等其他的标准。
事务技术介绍
以Spring+Mybatis+JDBC+Mysql为例,常见的事务类请求的调用链路如下图。请求调用应用服务,应用服务中开启事务并进行业务操作,操作过程中调用Mybatis进行数据库类操作,Mybatis通过JDBC驱动与底层数据库交互。
因此接下来先按Mysql、JDBC、Mybatis、Spring来介绍各层的事务相关知识;最后进行全链路的调用分析。
Mysql事务相关
Mysql逻辑架构
架构图如下(InnoDB存储引擎):
MySQL事务是由存储引擎实现的,MySQL支持事务的存储引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最为广泛,其他存储引擎如MyIsam、Memory等不支持事务。
Mysql的事务保证
Mysql的4个特性中有3个与 WAL(Write-Ahead Logging,先写日志,再写磁盘)有关系,需要通过 Redo、Undo 日志来保证等,而一致性需要通过DBMS的功能逻辑及原子性、隔离性、持久性共同来保证。
MVCC
MVCC最大的好处是读不加锁,读写不冲突,在读多写少的系统应用中,读写不冲突是非常重要的,可极大提升系统的并发性能,这也是为什么现阶段几乎所有的关系型数据库都支持 MVCC 的原因,目前MVCC只在 Read Commited 和 Repeatable Read 两种隔离级别下工作。它是通过在每行记录的后面保存两个隐藏列来实现的,这两个列, 一个保存了行的创建时间,一个保存了行的过期时间, 存储的并不是实际的时间值,而是系统版本号。MVCC在mysql中的实现依赖的是undo log与read view。
read view
在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read)与当前读 (Current Read)。
•快照读:读取的是记录的快照版本(有可能是历史版本)不用加锁(select)。
•当前读:读取的是记录的最新版本,并且当前读返回的记录,都会加锁,保证其他事务不会再并发修改这条记录(select… for update 、lock或insert/delete/update)。
redo log
redo log叫做重做日志。mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Buffer Pool(缓冲池)里,当作缓存来用以提升性能,使用后台线程去做缓冲池和磁盘之间的同步。那么问题来了,如果还没来及的同步的时候宕机或断电了怎么办?这样会导致丢部分已提交事务的修改信息!所以引入了redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后再读取redo log恢复最新数据。redo log是用来恢复数据的,保障已提交事务的持久化特性。
undo log
undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log主要记录的是数据的逻辑变化。为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。undo log 记录事务修改之前版本的数据信息,假如由于系统错误或者rollback操作而回滚的话可以根据undo log的信息来进行回滚到没被修改前的状态。undo log是用来回滚数据的,保障未提交事务的原子性。
示例
假设 F1~F6 是表中字段的名字,1~6 是其对应的数据。后面三个隐含字段分别对应该行的隐含ID、事务号和回滚指针,如下图所示。
具体的更新过程如下:
假如一条数据是刚 INSERT 的,DB_ROW_ID 为 1,其他两个字段为空。当事务 1 更改该行的数据值时,会进行如下操作,如下图所示。
•用排他锁锁定该行,记录 Redo log;
•把该行修改前的值复制到 Undo log,即图中下面的行;
•修改当前行的值,填写事务编号,并回滚指针指向 Undo log 中修改前的行。
如果再有事务2操作,过程与事务 1 相同,此时 Undo log 中会有两行记录,并且通过回滚指针连在一起,通过当前记录的回滚指针回溯到该行创建时的初始内容,如下图所示,这里的undolog不会一直增加,purge thread在后面会进行undo page的回收,也就是清理undo log。
JDK事务相关
JDBC规范
java定义了统一的JDBC驱动API,各数据库厂商按规范实现。jdbc驱动相关包在java.sql包下:
使用示例:
JDBC驱动注册机制
之前需要调用Class.forName或其他方式显式加载驱动,现在有了SPI机制后可不写。
JTA规范
JTA 全称 Java Transaction API,是 X/OPEN CAE 规范中分布式事务 XA 规范在 Java 中的映射,是 Java 中使用事务的标准 API,同时支持单机事务与分布式事务。
作为 J2EE 平台规范的一部分,JTA 与 JDBC 类似,自身只提供了一组 Java 接口,需要由供应商来实现这些接口,与 JDBC 不同的是这些接口需要由不同的供应商来实现。
相关代码在jta jar的javax.transaction包下。
Mybatis事务相关
Mybatis核心是提供了sql查询方法、结果集与应用方法及对象之间的映射关系,便于开发人员进行数据库操作。
整体模块如下:
各模块与下面的各子包一一对应:
Mybatis执行的核心类如下:
Mysql的核心入口类为SqlSession,事务相关的操作通过TransactionFactory来处理,可选择使用Spring事务(SpringManagedTransaction)还是内置事务管理。
事务相关的控制处理可见SqlSessionInterceptor类,主要逻辑如下:
源码见下:
Spring事务相关
spring事务相代码主要位于spring-tx包,如TransactionInterceptor。spring-jdbc包中有spring jdbc对事务的相关支持实现,如JdbcTransactionManager。核心类如下图,主要有三大部分:事务管理器(TransactionManager)、事务定义(TransactionDefinition)、事务状态(TtransactionStatus),这也是经常见的一种架构思维,将功能模块抽象为配置态定义、运行态实例和执行引擎,在开源组件jd-easyflow(
https://github.com/JDEasyFlow/jd-easyflow) 中也是此种设计理念。从下面的类图可以Spring的设计非常有层次化,很有美感。
Spring编程式事务
常用类为TransacitonTemplate,执行逻辑为:获取事务状态->在事务中执行业务->提交或回滚,源码见下:
Spring声明式事务
声明式事务实现原理就是通过AOP/动态代理。
在Bean初始化阶段创建代理对象:Spring容器在初始化每个单例bean的时候,会遍历容器中的所有BeanPostProcessor实现类,并执行其
postProcessAfterInitialization方法,在执行AbstractAutoProxyCreator类的postProcessAfterInitialization方法时会遍历容器中所有的切面,查找与当前实例化bean匹配的切面,这里会获取事务属性切面,查找@Transactional注解及其属性值,然后根据得到的切面创建一个代理对象,默认是使用JDK动态代理创建代理,如果目标类是接口,则使用JDK动态代理,否则使用Cglib。
在执行目标方法时进行事务增强操作:当通过代理对象调用Bean方法的时候,会触发对应的AOP增强拦截器,声明式事务是一种环绕增强,对应接口为MethodInterceptor,事务增强对该接口的实现为TransactionInterceptor,类图如下:
事务拦截器TransactionInterceptor在invoke方法中,通过调用父类TransactionAspectSupport的invokeWithinTransaction方法进行事务处理,包括开启事务、事务提交、异常回滚 。
声明式事务有5个配置项,说明如下:
事务配置一、事务隔离级别
配置该事务的隔离级别,一般情况数据库或应用统一设置,不需要单独设值。
事务配置二、事务传播属性
事务传播属性是spring事务模块的一个重要属性。简单理解,他控制一个方法在进入事务时,在外层方法有无事务的场景下,自己的事务的处理策略,如是复用已有事务还是创建新事务。
spring支持的传播属性有7种,如下:
事务配置三、事务超时
事务的超时设置是为了解决什么问题呢?
在数据库中,如果一个事务长时间执行,这样的事务会占用不必要的数据库资源,还可能会锁定数据库的部分资源,这样在生产环境是非常危险的。这时就可以声明一个事务在特定秒数后自动回滚,不必等它自己结束。
事务超时时间的设置
由于超时时间在一个事务开启的时候创建的,因此,只有对于那些具有启动一个新事务的传播行为(PROPAGATION_REQUIRES_NEW、PROPAGATION_REQUIRED、ROPAGATION_NESTED),声明事务超时才有意义。
事务配置四、事务只读
如果一个事务只对数据库进行读操作,数据库可以利用事务的只读特性来进行一些特定的优化。我们可以通过将事务声明为只读,让数据库对我们的事务操作进行优化。
事务配置五、回滚规则
回滚规则,就是程序发生了什么会造成回滚,这里我们可以进行设置RuntimeException或者Error。
默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚。
我们可以声明事务在遇到特定的异常进行回滚。同样,我们也可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常。
声明式事务失效的场景
事务同步管理器
Spring中有一个事务同步管理器类
TransactionSynchronizationManager,它提供了事务提交后处理等相关回调注册的方法。当我们有业务需要在事务提交过后进行某一项或者某一系列的业务操作时候我们就可以使用
TransactionSynchronizationManager。
事务请求处理链路示例
下图为全链路的从应用发起到开启事务,到业务逻辑处理(SQL执行),最后关闭事务的正向链路。
事务实践相关
数据一致性
同一个数据源的操作在一个事务内可保证一致,但实际场景中会因为不同事务或不同数据源(不同关系数据库、缓存或远端服务)而导致数据不能强一致。在CAP理论框架下,我们一般是保证可用性、分区容错性,基于BASE理论达到最终一致性。但如何达到数据的最终一致性需要合理设计。
数据库的提交、缓存的更新、RPC的执行、消息的发送的先后顺序
一般我们以数据库数据为准,先数据库提交,再更新缓存或发送消息,通过异步轮询补偿的方式保证异常情况下的最终一致性。
不建议用法:
1、事务回滚会导致缓存和数据库不一致
2、事务回滚会导致消息接收方收到的数据状态错误
建议用法:
1、先更新数据库,事务提交后再更新缓存或发送消息
2、通过异步异常重试或批处理同步来保证数据的最终一致性
3、核心交易以数据库数据为准
系统健壮性增强,但编程模型复杂一些
长事务
如果事务中有耗时长的SQL或有RPC操作可能会导致事务时间变长,会导致并发量大的情况下数据库连接池被占满,应用无法获取连接资源,在主从架构中会导致主从延时变大。
建议事务粒度尽量小,事务中尽量少包含RPC操作。事务尽量放在下层。
不建议用法
建议用法
这种方式需要应用程序保证多个事务操作的最终一致性,一般可通过异常重试来实现。
事务代码层级
事务该加在哪一层?放在上层的优点是编程简单,放在底层则需要需要在一个事务的操作封装在一起沉淀到底层。
对于传统架构(如下图),建议在DAO层和Manager层加事务。Service层可以有,但重的Service或有rpc的Service操作慎用。
对于领域设计类架构(如下图),从DDD的思想上,建议放在APP层(基础设施不应是领域层关注的),但考虑到长事务问题,不建议放在APP层,更建议优先放在基础设施层,domain的service层也可有。
总结
以上对事务的常用知识进行了总结整理,相关实践规范有的并无完美固定答案,需要结合实际而论,欢迎大家留言沟通!
作者:翟贺龙
一、背景
在计算机领域,涉及性能优化动作时首先应被考虑的原则之一便是使用缓存,合理的数据缓存机制能够带来以下收益:
缩短数据获取路径,热点数据就近缓存以便后续快速读取,从而明显提升处理效率;
降低数据远程获取频次,缓解后端数据服务压力、减少前端和后端之间的网络带宽成本;
从 CPU 硬件的多级缓存设计,到浏览器快速展示页面,再到大行其道的 CDN、云存储网关等商业产品,处处应用了缓存理念。
在公网领域,如操作系统、浏览器和移动端 APP 等成熟产品所具备的缓存机制,极大的消解了网络提供商如电信移动联通、内容提供商如各大门户平台和 CDN 厂商直面的服务压力,运营商的 DNS 才能从容面对每秒亿万级的 DNS 解析,网络设备集群才能轻松承担每秒 Tbit 级的互联网带宽,CDN 平台才能快速处理每秒亿万次的请求。
面对公司目前庞大且仍在不断增长的的域名接入规模,笔者所在团队在不断优化集群架构、提升 DNS 软件性能的同时,也迫切需要推动各类客户端环境进行域名解析请求机制的优化,因此,特组织团队成员调研、编写了这篇指南文章,以期为公司、客户及合作方的前端开发运维人员给出合理建议,优化 DNS 整体请求流程,为业务增效。
本文主要围绕不同业务和开发语言背景下,客户端本地如何实现 DNS 解析记录缓存进行探讨,同时基于笔者所在团队对 DNS 本身及公司网络环境的掌握,给出一些其他措施,最终致力于客户端一侧的 DNS 解析请求规范化。
二、名词解释
1. 客户端
本文所述客户端,泛指所有主动发起网络请求的对象,包括但不限于服务器、PC、移动终端、操作系统、命令行工具、脚本、服务软件、用户 APP 等。
2. DNS
Domain Name System(Server/Service),域名系统(服务器/服务),可理解为一种类数据库服务;
客户端同服务端进行网络通信,是靠 IP 地址识别对方;而作为客户端的使用者,人类很难记住大量 IP 地址,所以发明了易于记忆的域名如 www.jd.com,将域名和 IP 地址的映射关系,存储到 DNS 可供客户端查询;
客户端只有通过向 DNS 发起域名解析请求从而获取到服务端的 IP 地址后,才能向 IP 地址发起网络通信请求,真正获取到域名所承载的服务或内容。
参考:域名系统 域名解析流程
3. LDNS
Local DNS,本地域名服务器;公网接入环境通常由所在网络供应商自动分配(供应商有控制权,甚至可作 DNS 劫持,即篡改解析域名得到的 IP),内网环境由 IT 部门设置自动分配;
通常 Unix、类Unix、MacOS系统可通过 /etc/resolv.conf 查看自己的 LDNS,在 nameserver 后声明,该文件亦支持用户自助编辑修改,从而指定 LDNS,如公网常见的公共 DNS 如谷歌 DNS、114DNS 等;纯内网环境通常不建议未咨询IT部门的情况下擅自修改,可能导致服务不可用;可参考 指令结果。
当域名解析出现异常时,同样应考虑 LDNS 服务异常或发生解析劫持情况的可能。
参考:windows系统修改TCP/IP设置(含DNS);
4. hosts
DNS 系统可以动态的提供域名和IP的映射关系,普遍存在于各类操作系统的hosts文件则是域名和IP映射关系的静态记录文件,且通常 hosts 记录优先于 DNS 解析,即本地无缓存或缓存未命中时,则优先通过 hosts 查询对应域名记录,若 hosts 无相关映射,则继续发起 DNS 请求。关于 Linux 环境下此逻辑的控制,请参考下文 C/C++ 语言 DNS 缓存介绍部分。
所以在实际工作中,常利用上述默认特性,将特定域名和特定 IP 映射关系写到 hosts 文件中(俗称“固定 hosts”),用于绕开 DNS 解析过程,对目标 IP 作针对性访问(其效果与 curl 的-x选项,或 wget 的 -e 指定 proxy 选项,异曲同工);
5. TTL
Time-To-Live,生存时间值,此概念在多领域适用且可能有不同意义。
本文涉及到 TTL 描述均针对数据缓存而言,可直白理解为已缓存数据的“有效期”,从数据被缓存开始计,在缓存中存在时长超过 TTL 规定时长的数据被视为过期数据,数据被再次调用时会立刻同权威数据源进行有效性确认或重新获取。
因缓存机制通常是被动触发和更新,故在客户端的缓存有效期内,后端原始权威数据若发生变更,客户端不会感知,表现为业务上一定程度的数据更新延迟、缓存数据与权威数据短时不一致。
对于客户端侧 DNS 记录的缓存 TTL,我们建议值为 60s;同时如果是低敏感度业务比如测试、或域名解析调整不频繁的业务,可适当延长,甚至达到小时或天级别;
三、DNS 解析优化建议
1. 各语言网络库对 DNS 缓存的支持调研
以下调研结果,推荐开发人员参考,以实现自研客户端 DNS 缓存。各开发语言对 DNS 缓存支持可能不一样,在此逐个分析一下。
C/C++ 语言
(1)glibc 的 getaddrinfo 函数
Linux环境下的 glibc 库提供两个域名解析的函数:gethostbyname 函数和 getaddrinfo 函数,gethostbyname 是曾经常用的函数,但是随着向 IPv6 和线程化编程模型的转移,getaddrinfo 显得更有用,因为它既解析 IPv6 地址,又符合线程安全,推荐使用 getaddrinfo 函数。
函数原型:
getaddrinfo 函数是比较底层的基础库函数,很多开发语言的域名解析函数都依赖这个函数,因此我们在此介绍一下这个函数的处理逻辑。通过 strace 命令跟踪这个函数系统调用。
1)查找 nscd 缓存(nscd 介绍见后文)
我们在 linux 环境下通过 strace 命令可以看到如下的系统调用
通过 unix socket 接口”/var/run/nscd/socket”连接nscd服务查询DNS缓存。
2)查询 /etc/hosts 文件
如果nscd服务未启动或缓存未命中,继续查询hosts文件,我们应该可以看到如下的系统调用
3)查询 DNS 服务
从 /etc/resolv.conf 配置中查询到 DNS 服务器(nameserver)的IP地址,然后做 DNS 查询获取解析结果。我们可以看到如下系统调用
而关于客户端是优先查找 /etc/hosts 文件,还是优先从 /etc/resolv.conf 中获取 DNS 服务器作查询解析,是由 /etc/nsswitch.conf 控制:
实际通过 strace 命令可以看到,系统调用 nscd socket 之后,读取 /etc/resolv.conf 之前,会读取该文件
4)验证
综上分析,getaddrinfo 函数结合 nscd ,是可以实现 DNS 缓存的。
(2)libcurl 库的域名解析函数
libcurl 库是 c/c++ 语言下,客户端比较常用的网络传输库,curl 命令就是基于这个库实现。这个库也是调用 getaddrinfo 库函数实现 DNS 域名解析,也是支持 nscd DNS 缓存的。
Java
Java 语言是很多公司业务系统开发的主要语言,通过编写简单的 HTTP 客户端程序测试验证 Java 的网络库是否支持 DNS 缓存。测试验证了 Java 标准库中 HttpURLConnection 和 Apache httpcomponents-client 这两个组件。
(1)Java 标准库 HttpURLConnection
测试结果显示 Java 标准库 HttpURLConnection 是支持 DNS 缓存,5 次请求中只有一次 DNS 请求。
(2)Apache httpcomponents-client
测试结果显示 Apache httpcomponents-client 支持 DNS 缓存,5 次请求中只有一次 DNS 请求。
从测试中发现 Java 的虚拟机实现一套 DNS 缓存,即实现在 java.net.InetAddress 的一个简单的 DNS 缓存机制,默认为缓存 30 秒,可以通过 networkaddress.cache.ttl 修改默认值,缓存范围为 JVM 虚拟机进程,也就是说同一个 JVM 进程中,30秒内一个域名只会请求DNS服务器一次。同时 Java 也是支持 nscd 的 DNS 缓存,估计底层调用 getaddrinfo 函数,并且 nscd 的缓存级别比 Java 虚拟机的 DNS 缓存高。
Go
随着云原生技术的发展,Go 语言逐渐成为云原生的第一语言,很有必要验证一下 Go 的标准库是否支持 DNS 缓存。通过我们测试验证发现 Go 的标准库 net.http 是不支持 DNS 缓存,也是不支持 nscd 缓存,应该是没有调用 glibc 的库函数,也没有实现类似 getaddrinfo 函数的功能。这个跟 Go语言的自举有关系,Go 从 1.5 开始就基本全部由 Go(.go) 和汇编 (.s) 文件写成的,以前版本的 C(.c) 文件被全部重写。不过有一些第三方 Go 版本 DNS 缓存库,可以自己在应用层实现,还可以使用 fasthttp 库的 httpclient。
(1)标准库net.http
从测试结果来看,net.http 每次都去 DNS 查询,不支持 DNS 缓存。
(2)fasthttp 库
fasthttp 库是 Go 版本高性能 HTTP 库,通过极致的性能优化,性能是标准库 net.http 的 10 倍,其中一项优化就是支持 DNS 缓存,我们可以从其源码看到
可以参考如下方法使用 fasthttp client 端
(3)第三方DNS缓存库
这个是 github 中的一个 Go 版本 DNS 缓存库
可以参考如下代码,在HTTP库中支持DNS缓存
Python
(1)requests 库
(2)httplib2 库
(3)urllib2 库
Python 测试三种库都是支持 nscd 的 DNS 缓存的(推测底层也是调用 getaddrinfo 函数),以上测试时使用 HTTP 短连接,都在 python2 环境测试。
总结
针对 HTTP 客户端来说,可以优先开启 HTTP 的 keep-alive 模式,可以复用 TCP 连接,这样可以减少 TCP 握手耗时和重复请求域名解析,然后再开启 nscd 缓存,除了 Go 外,C/C++、Java、Python 都可支持 DNS 缓存,减少 DNS查询耗时。
这里只分析了常用 C/C++、Java、Go、Python 语言,欢迎熟悉其他语言的小伙伴补充。
2. Unix/类 Unix 系统常用 dns 缓存服务:
在由于某些特殊原因,自研或非自研客户端本身无法提供 DNS 缓存支持的情况下,建议管理人员在其所在系统环境中部署DNS缓存程序;
现介绍 Unix/类 Unix 系统适用的几款常见轻量级 DNS 缓存程序。而多数桌面操作系统如 Windows、MacOS 和几乎所有 Web 浏览器均自带 DNS 缓存功能,本文不再赘述。
P.S. DNS 缓存服务请务必确保随系统开机启动;
nscd
name service cache daemon 即装即用,通常为 linux 系统默认安装,相关介绍可参考其 manpage:;
(1)安装方法:通过系统自带软件包管理程序安装,如
(2)缓存管理(清除):
重启服务清除所有缓存;
清除 hosts 表中的域名缓存(hosts 为域名缓存使用的 table 名称,nscd 有多个缓存 table,可参考程序相关 manpage)
dnsmasq
较为轻量,可选择其作为 nscd 替代,通常需单独安装
(1)安装方法:通过系统自带软件包管理程序安装,如
(2)核心文件介绍(基于 Dnsmasq version 2.86,较低版本略有差异,请参考对应版本文档如 manpage 等)
(3)/etc/default/dnsmasq 提供六个变量定义以支持六种控制类功能
(4)/etc/dnsmasq.d/ 此目录含 README 文件,可参考;目录内可以存放自定义配置文件
(5)/etc/dnsmasq.conf 主配置文件,如仅配置 dnsmasq 作为缓存程序,可参考以下配置
(6)缓存管理(清除):
推荐方式,无需重启服务
或
或
(7)官方文档:https://thekelleys.org.uk/dnsmasq/doc.html
3. 纯内网业务取消查询域名的AAAA记录的请求
以 linux 操作系统为例,常用的网络请求命令行工具常常通过调用 getaddrinfo() 完成域名解析过程,如 ping、telnet、curl、wget 等,但其可能出于通用性的考虑,均被设计为对同一个域名每次解析会发起两个请求,分别查询域名 A 记录(即 IPV4 地址)和 AAAA 记录(即 IPV6 地址)。
因目前大部分公司的内网环境及云上内网环境还未使用 ipv6 网络,故通常 DNS 系统不为内网域名添加 AAAA 记录,徒劳请求域名的 AAAA 记录会造成前端应用和后端 DNS 服务不必要的资源开销。因此,仅需请求内网域名的业务,如决定自研客户端,建议开发人员视实际情况,可将其设计为仅请求内网域名 A 记录,尤其当因故无法实施本地缓存机制时。
4. 规范域名处理逻辑
客户端需严格规范域名/主机名的处理逻辑,避免产生大量对不存在域名的解析请求(确保域名从权威渠道获取,避免故意或意外使用随机构造的域名、主机名),因此类请求的返回结果(NXDOMAIN)通常不被缓存或缓存时长较短,且会触发客户端重试,对后端 DNS 系统造成一定影响。
作者:贾世闻
我们在开发应用后端系统的时候经常要和各种数据库、缓存等资源打交道。这一期,我们聊聊如何访问redis 并将资源池化。
在一个应用后端程序访问redis主要要做的工作有两个,单例和池化。
在后端应用集成redis,我们主要用到以下几个crate:[once_cell](https://github.com/matklad/once_cell)、[redis-rs](https://github.com/redis-rs/redis-rs)、[r2d2](https://github.com/sfackler/r2d2).once_cell 实现单例;redis-rs 是 redis的 rust 驱动;r2d2 是一个池化连接的工具包。本期代码均出现在[fullstack-rs](https://github.com/jiashiwen/fullstack-rs)项目中。[fullstack-rs](https://github.com/jiashiwen/fullstack-rs)是我新开的一个实验性项目,目标是做一个类似[gin-vue-admin](https://github.com/flipped-aurora/gin-vue-admin)的集成开发框架。
redis资源的定义主要是在https://github.com/jiashiwen/fullstack-rs/blob/main/backend/src/resources/redis_resource.rs 中实现的。
一、redis-rs 封装
在实际开发中,我们面对的redis资源可能是单实例也有可能是集群,在这里我们对redis-rs进行了简单封装,便于适应这两种情况。
RedisInstance,定义redis资源的描述,与配置文件相对应。详细的配置描述可以参考 https://github.com/jiashiwen/fullstack-rs/blob/main/backend/src/configure/config_global.rs 文件中 RedisConfig 和 RedisPool 两个 struct 描述。
RedisClient 和 RedisConnection 对redis 的链接进行了封装,用来实现统一的调用接口。
二、基于 r2d2 实现 redis 连接池
以上,基本完成的reids资源的准备工作,下面来实现一个redis链接池。
利用 r2d2 来实现连接池需要实现 r2d2::ManageConnection trait。connect 函数获取连接;is_valid 函数校验连通性;has_broken 判断连接是否崩溃不可用。
gen_redis_conn_pool 函数用来生成一个 redis 的连接池,根据配置文件来指定连接池的最大连接数,最小闲置连接以及连接超时时长。
三、连接池单例实现
在后端开发中,对于单一资源一般采取单例模式避免重复产生实例的开销。下面来聊一聊如果构建一个全局的 redis 资源。
这一部分代码在https://github.com/jiashiwen/fullstack-rs/blob/main/backend/src/resources/init_resources.rs 文件中。
利用 OnceCell 构建全局静态变量。
init_global_redis 函数,用来初始化 GLOBAL_REDIS_POOL 全局静态变量。在一般的后端程序中,资源是强依赖,所以,初始化简单粗暴,要么成功要么 panic。
四、资源调用
准备好 redis 资源后,我们聊聊如何调用。
调用例子在这里https://github.com/jiashiwen/fullstack-rs/blob/main/backend/src/httpserver/service/service_redis.rs
https://github.com/jiashiwen/fullstack-rs/tree/main/backend 这个工程里有从http入口开始到写入redis的完整流程,http server 不在本文讨论之列,就不赘述了,有兴趣的同学可以去github看看。
咱们下期见。
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
系统介绍
ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。
系统完全开源,基于 Apache 2.0 开源协议。
功能特性
- 丰富的模块市场,后台一键快速安装
- 会员模块通用且完整,支持完整的API调用
- 大文件分片上传,进度条显示,已上传文件管理
- 强大的模块扩展功能,所有模块可以无缝集成,支持在线安装、卸载模块
- 完善的开发助手,实现模块、主题的的一键创建
- 完善的后台权限管理,支持基于RBAC的权限管理系统
- 后台管理支持使用手机、平板、PC,无论何时何地都可方便管理
- 第三方登录(、微信、微博、支付宝、微信小程序)
- 第三方支付支持(微信、支付宝、支付宝当面付、微信扫码、微信小程序)
- 第三方云存储支持,支持云储存分片上传(阿里云、百度云、华为云、腾讯云、FTP、七牛云、UCloud、又拍云)
- 第三方短信支持(阿里云、腾讯云、华为云、百度云、253云通讯、聚合、七牛云、融云、赛邮、UCloud、云片、网易云)
V6.3.0版本更新
2022年12月07日ModStartBlog发布v6.3.0版本,增加了以下9个特性:
- [新功能] 任务调度新增上次运行时间设定
- [新功能] 任务调度记录调度日志和调度结果
- [新功能] 响应新增永久重定向方法 redirectPermanently
- [新功能] 补全部分数据库模型文件
- [新功能] 文件上传预期错误重传机制
- [新功能] 数字动态增长组件,数字动态显示效果
- [新功能] UEditorPlus升级2.7.0版本
- [Bug修复] 浏览器自适应或尺寸变更时轮播自动更新
- [Bug修复] Detail页面为模型时异常问题
模块市场一键安装
系统内置模块市场,有行业应用、插件、云存储、云短信等功能模块,后台支持一键安装、启用、禁用、卸载,可快速搭建属于自己的系统应用。
系统演示与文档
- 码云仓库:https://gitee.com/modstart/ModStartBlog
- Github仓库:https://github.com/modstart/ModStartBlog
- 系统演示:https://blog.demo.tecmz.com/
- 下载试用:https://modstart.com/download
- 开发者文档:https://modstart.com/doc
- 模块市场:https://modstart.com/store
漏洞描述
Apache ManifoldCF 是一个具有多种连接器的多存储库爬虫框架。
Apache ManifoldCF 2.23及之前版本中由于 ActiveDirectoryAuthority.java 类没有对用户的用户名或域字符串进行有效过滤,导致 Apache ManifoldCF 的 ActiveDirectory 和 Sharepoint ActiveDirectory 权限连接器存在 LDAP 注入漏洞。攻击者可在用户进行 LDAP 查询期间注入恶意搜索字符进行 LDAP 注入攻击,从而获取对 Apache ManifoldCF 系统目录的未授权访问权限,查看或修改系统目录中的敏感文件信息或造成程序崩溃。
影响范围
org.apache.manifoldcf:mcf-activedirectory-connector@(-∞, 2.24)
org.apache.manifoldcf:mcf-sharepoint-connector@(-∞, 2.24)
修复方案
升级org.apache.manifoldcf:mcf-activedirectory-connector到 2.24 或更高版本
升级org.apache.manifoldcf:mcf-sharepoint-connector到 2.24 或更高版本
参考链接
https://www.oscs1024.com/hd/MPS-2022-65273
https://nvd.nist.gov/vuln/detail/CVE-2022-45910
https://github.com/apache/manifoldcf/commit/7df176b2a73ebea2dd3e319c7e9fc68bc162bab8
https://github.com/apache/manifoldcf/commit/4bc75e6aa0cefce5e4e3c45680d543bff5f3ed73
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
一股“神秘力量”使得知名前端框架 Vue 的周 npm 下载量激增十倍,以至于 Vue 创始人尤雨溪发推解释:“我也不知道谁搞出来的,请搞出这事的人赶紧修复吧,这样会搞得统计数据毫无意义。”
从 NPM Trends 页面上可以看到,上上周 (11 月 27 日)的 vue npm 下载量达到惊人的 3800 万,比前一周(11 月 20 日 )的 360 万下载量暴增了十倍。而其他前端框架,如 React 和 angular 都没有明显的波动。
反而是另一款前端 UI 框架 Svelte 也经历了过山车式的体验,周下载量先是从日常 40 万飙升到 2800 万,然后又狠狠地下跌,但仍未恢复至正常水平。
热心网友建议尤雨溪直接问 npm 官方,但是 Svelte 框架作者 Rich Harris 表示他已经尝试过和 npm 方面沟通,然而 npm 官方无法透露任何有用的信息,目前只知道 UA 来自 Deno,其他情况一概不知 。
大伙纷纷在尤雨溪的推文下面评论调侃,猜测 Npm 下载量暴涨的原因:Vue 框架贡献者 Johnson Chu 称这也许是一项行为艺术,以此来表达通过下载量来比较前端框架毫无意义。
又有网友认为也许是最近火热的 chatGPT AI 正在大量学习如何制作 Vue 应用程序,在每次迭代中都会运行 npm install,导致下载量暴增。此外,也有人认为该事件与 Nuxt 框架 3.0 版本的正式发布有关,Nuxt 3.0 版本基于 Vue 3 构建,可能会导致 Vue 的下载量暴增。
但导致 Vue npm 下载量暴增的原因尚未有明确的定论,只能等下一轮 npm 统计数据或者官方公告,我们会密切跟踪后续发展。
近日,平头哥半导体有限公司(以下简称“平头哥”)签署openKylin社区CLA(Contributor License Agreement 贡献者许可协议),正式加入openKylin开源社区。
平头哥成立于2018年9月19日,是阿里巴巴集团的全资半导体芯片业务主体。作为高性能RISC-V处理器的先行者,平头哥不断拓展RISC-V性能、应用与生态的边界,打造出从低功耗、低成本到高性能、高能效的丰富RISC-V处理器产品家族,广泛应用于边缘计算、无线通讯、工业控制、通用MCU等30多个领域及应用场景。
在加入openKylin社区后,平头哥积极参与社区合作,推动openKylin与RISC-V架构融合发展。目前,平头哥已与openKylin社区合作,完成了平头哥曳影 1520 SoC与openKylin操作系统的适配工作,并基于社区软件源构建了镜像版本。
该版本包含近1600个软件包,集成了一系列稳定版本的基础库和图形开发库,能够顺畅运行UKUI桌面环境。此外,系统包含丰富的openKylin自研软件和第三方开源软件,如浏览器、视频、音频和文档编辑等,可以满足用户的基本使用需求。
社区会员持续招募中
目前,openKylin社区会员招募正在火热进行中,欢迎更多企业伙伴加入,携手共建,打造桌面操作系统顶级社区,推动国产操作系统产业生态健康发展。详情可查看:【https://sigusoft.com/s/yk82DEQSG0knaQNKyc-vsg 】
openKylin(开放麒麟)社区旨在以“共创”为核心,在开源、自愿、平等、协作的基础上,通过开源、开放的方式与企业构建合作伙伴生态体系,共同打造桌面操作系统顶级社区,推动Linux开源技术及其软硬件生态繁荣发展。
社区首批理事成员单位包括麒麟软件、普华基础软件、中科方德、麒麟信安、凝思软件、一铭软件、中兴新支点、心科技、中国电科32所、技德系统、北京麟卓、先进操作系统创新中心等13家产业同仁和行业机构。
审核:openKylin
为推动社区繁荣发展,打造开源操作系统创新生态, openKylin(开放麒麟)社区根据领域划分了不同的SIG组,并积极开展各种技术研究和创新。其中,11月份社区新增SIG小组4个,共有56个SIG组在运行,接下来,让我们一起盘点11月份openKylin社区SIG组的最新技术进展:
社区新增SIG
InputSolution SIG
致力于组建openKylin社区输入法解决方案框架特殊兴趣小组以及输入法解决方案开源社区,推进输入法解决方案框架在社区落地并维护。
RTHypervisor SIG
致力于实时虚拟化技术的研究,目前主要包括jailhouse。提供工控、车载等领域实时控制的虚拟化解决方案。
GPU SIG致力于GPU驱动相关技术研究,包括OpenGL、OpenCL、Vulkan、VDPAU和VAAPI等。提供GPU相关软件包的技术规划、设计、开发、维护和升级服务,共同推动国产GPU技术发展。
Easylosu SIG
负责为开放麒麟开发简单高效的编程语言,致力于让用户以最低的门槛,轻松享受编程的便利,促进编程语言国产化,促进开放麒麟在非开发者群体的推广。
openKylin社区技术进展与成果
一、UKUI SIG
UKUI(Ultimate Kylin User Interface) SIG小组致力于桌面环境相关软件包的规划、维护和升级工作,满足各种设备和用户需求的桌面环境程序,主要包含程序启动器(开始菜单)、用户配置、文件管理、登录锁屏、桌面、网络工具、快捷配置等,为用户提供基本的图形化操作平台。11月进展如下:
- 推进0.9版本遗留bug修复;
- 1.0计划剩余需求合入;
- 推进新增bug的修复,包括:修复定时关机翻译、控制面板设置网络后被最小化、平板切PC窗口三联状态未恢复、插拔HDMI显示器分辨率异常、蓝牙耳机未自动回连、外接4K显示器显示异常、电量即将耗尽时未弹窗、工具箱偶现闪退、锁屏界面无电量状态等bug;
- UKUI网站信息更新与新版网站设计稿评审;
- 推动UKUI移除包列表移入对应SIG组;
- 解决任务栏与开始菜单显示位置异常问题;
- 通知、网络、电源管理、控制面板、USD完成需求,合入最新代码;
- 新增可变强度毛玻璃特效;
- 企业网新增LEAP、PWD、FAST认证类型需求;
- UKUI网站更新:敲定产品特性、社区展示页等设计素。
欢迎各位感兴趣的社区开发者加入我们,一起打造openKylin桌面系统稳定易用的桌面环境!
二、RISC-V SIG
本SIG组主要负责RISC-V架构开源软件包的维护,发布openKylin的RISC-V版本,进行软件包构建、系统构建等工作。
- 完成专利“一种面向RISC-V的可扩展分段自动化镜像构建技术”初稿以及相关脚本的编写;
- 交叉编译opensbi、内核并解决相关问题。RVTrans增加了对于GtkApplication、GApplication、GtkTextView3、GtkTextContainer3的支持;
- 解决了运行扫雷等gtk应用问题;
- 平头哥开发板构建完成符合开发板要求的rootfs镜像,后续需要继续调试优化;
- 封装GTK3相关类及运行扫雷等小游戏需要的动态库函数,增加或修改代码400+行,增强了对RVTrans对于Gtk3的支持;
- 平头哥曳影1520开发板适配:
- (1)系统镜像已通过修改uboot环境变量的方法成功设置分区,测试已能够正常烧录镜像并且能够正常启动我们制作的rootfs;
- (2)适配RISC-V原生Firefox和LibreOffice,进度完成20%;
- rvtrans:
- (1)增加了对于GtkButton3、GamesScoresImporter类及libgnome-game-support动态库的封装,增强了对于gnome游戏的支持;
- (2)封装了运行gtk应用必须的动态库函数30+;
- (3)解决了缺少g_object_connect相关回调函数问题。
欢迎所有对RISC-V技术方向感兴趣的爱好者加入到RISC-V SIG!
三、Virtualization SIG
Virtualization SIG致力于构建openKylin社区系统虚拟化技术,打造面向端、边、云的全场景虚拟化解决方案。本SIG组11月份主要进展如下:
- virtio-gpu 硬件编码框架virglerenderer补丁集已被上游社区接受;
- 向极狐社区gitlab云原生沙龙会议提供主题和专家资料;
- 修复qemu 7.1编译错误,暂时关闭qemu uring支持;
- 添加仓库spice libvirt spice-protocol;
- virglrender移植上游virtio-gpu硬件加速编解码补丁;
- qemu 添加virtio-gpu硬件加速补丁以及运行依赖相关库12个;
- 新增6个虚拟化依赖包,解决在openkylin上打包失败的问题;
- 修复libvirt运行崩溃问题。
欢迎所有对虚拟化技术方向感兴趣的爱好者加入到Virtualization SIG!
四、Release SIG
Release SIG主要负责协调各个SIG组,把控版本开发进度和风险,制定版本发布计划,完成版本发布工作等。Release SIG本月主要进展如下:
- 筛选影响较大的严重bug 34个,推进修复27个,正式发布openkylin 0.9版本,开启公测;
- 梳理所有开发、项目管理、规则流程文档,编写社区签署CLA参与指南、提交和审核issue指南;
- 社区需求管理规范定稿;
- 确定1.0alpha、beta、RC版本计划;
- 推进软件商店和UKUI需求排期;
- 1.0 版本宣传亮点梳理;
- 社区看板功能对接讨论;
欢迎所有对openKylin社区版本集成、版本管理、版本发行等工作感兴趣的爱好者加入到Release SIG!
五、Kernel SIG
Kernel SIG负责openKylin社区版本的内核选型、代码维护等工作。本月主要进展如下:
- 完成分级冻结机制内核补丁的开发、移植。
欢迎所有对openKylin社区内核开发维护感兴趣的爱好者加入到Kernel SIG!
六、Framework SIG
Framework SIG致力于为openKylin社区提供集程序编辑、编译、调试、发布、分析等全套开发功能的编程环境,涵盖通用集成开发环境、编译工具链、运行时环境、类库等。SIG初期重点研制高效率、跨平台、插件化、易调试的通用集成开发环境,支持C、C++、Java、Go、Fortran、Python、JavaScript等多种标准编程语言,涵盖编码、编译、调试、性能分析、软件交付等一整套开发流程,满足openKylin平台上软件开发需求。本月主要进展如下:
- 修复优化同时持续推进CMake智能编辑、分布式编译集成插件、死锁检测、代码性能分析、项目创建等功能开发;
欢迎所有对openKylin社区应用集成开发环境感兴趣的爱好者加入到Framework SIG!
七、Infrastructure SIGInfrastructure SIG负责openKylin社区的基础平台系统功能的开发、维护。本月主要进展如下:
- CI平台
- (1)增加changelog格式检查功能、打包上传后跟踪OKBS处理情况、打包成功自动关闭旧的issue;
- (2)修复部分软件包gbp.conf启用tag签名导致打包失败的问题;
- 数字看板
- (1)与小程序端进行接口联调上线;
- (2)支持查看SIG成员贡献详情;
- CLA平台
- (1)支持第三方供应商推广个人CLA签署;
- (2)企业会员增加logo管理功能,增加重置企业管理员密码功能,增加会员证书等文件。
欢迎所有对openKylin社区基础设施平台开发维护感兴趣的爱好者加入到Infrastructure SIG!
八、Defend SIG
Defend SIG组致力于在openKylin社区版本中引入的系统防护功能。SIG组11月份主要进展如下:
- 组织Defend SIG组第一次公开例会,邀请社区会员山石网科安全专家参加交流;
- openKylin安全防护软件功能模块继续梳理。
欢迎所有对操作系统防护软件感兴趣的爱好者加入到Defend SIG!
九、Xfce/KDE SIG
主要负责维护Xfce和KDE桌面环境在openKylin社区的适配和发展。11月份SIG组主要进展如下:
- Xfce桌面环境的所有组件已上传完毕,通过OKBS软件包编译平台发布到了openKylin proposed源,可以安装和使用。当前处于日常维护状态,本月修复一个CVE-2022-45062漏洞。
- KDE桌面环境的基本组件已上传完毕,通过OKBS软件包编译平台发布到了openKylin proposed源,可以安装和使用。目前移植了KDE的部分图形类、网络类和游戏类等应用,将进行日常维护和继续移植更多的KDE应用。
欢迎各位感兴趣的社区爱好者,一同加入我们!
十、Docs SIG
Docs SIG小组致力于创建openKylin社区各种文档,包括但不限于使用文档、开发文档、各类教程等等,帮助社区新人和开发人员更好的使用、开发openKylin版本及周边。Docs SIG 11月份进展如下:
- 主导更新openkylin SDK v2.0开发指南文档,并转换成markdown格式。
欢迎所有对文档编写、文档管理感兴趣的社区爱好者加入我们!
十一、Packaging SIG
Packaging SIG负责维护openKylin社区的软件包打包规范,维护公共软件包,以及协调和决策社区版本发布过程中的包依赖问题。11月份主要进展如下:
- python3.10、python2.7、llvm编译上传;
- 处理glibc、gcc、libkysdk-ocr-dev、libkysdk-sysinfo、libkysdk-sysinfo-dev、python3-stdlib-extensions、python3-defaults、python-pip、libjs-sphinxdoc、fakeroot、dh-python、glibc等版本升级工作,并处理依赖问题;
- 新增44个源码包;
- 解决gspell、perl等编译问题,升级更新fakeroot/glibc2.36、systemd251.4 ;
- 新增21个上游包,上传gitee13个软件包;
- 撰写《移植Hello软件到openKylin》;
- 分析python3.10、glibc,正在形成文档;
- 本地新编包6个,处理perl-5.36、gimp、xrdp、batik、remmina、openjdk-lts等软件包编译问题;
欢迎所有对openKylin社区软件自主选型、编译打包工作感兴趣的社区爱好者加入我们!
十二、QA SIG
QA SIG组致力于提升openKylin社区版本质量,包括社区版本测试、质量保障等。本月主要进展如下:
- RC-1101版本、RC-1102版本回归测试;
- 0.9发布版本测试(x86和RISC-V);
- 编写openKylin 0.9共测方案,已上传码云并同步给产品;
- 0.9版本测试报告完成并发送,剩余需求梳理及新节点确认,共测issue审核及评分,本周审核10个issue;
- openKylin 软件商店-新增openKylin ID登录支持需求 补丁包测试准备;
- 传书及openKylin漏洞修复测试完成。安全漏洞已修复,影响域测试传书基础功能测试通过,两个版本共执行禅道用例82条,通过76条,失败4条;
- 0.9版本共测活动Issue审核及评分处理;
- 新版软件商店及登录ID需求确认测试范围,提交7个issue包括6个高等级,发送初步测试结果;
- 编写1.0版本测试方案完成待评审;
- UKUI部分新需求编写测试用例;
欢迎所有对openKylin社区版本测试、质量管理感兴趣的社区爱好者加入我们!
十三、SecurityGovernance SIG
openKylin SecurityGovernance SIG通过接收和响应openKylin社区的产品安全问题报告、提供社区安全指导,开展安全治理等活动提升社区产品的安全性。本月主要进展如下:
- 规划了三个安全研发流程相关开源项目,提交相关的流程介绍、仓库及落地方案;
- poc仓库(openkylin-exploit-db),新增15个漏洞POC;
- fuzzing仓库
- (1)引入Google fuzz仓库技术文档内容;
- (2)新增原创技术文章3篇;
- 安全漏洞扫描框架仓库(genmai)
- (1)完成“诊脉”扫描框架的YAML和JSON配置文件的解析功能,并提交代码;
- (2)完成优化三个模块功能(沙箱接口模块,YAML配置解析模块,JSON配置解析模块),提交go代码两千多行;
- 攻防智库(attack-defense-think-tank)
- (1)新增收录5篇技术文章和应急响应工具箱。之后会持续将常见漏洞(如命令注入、目录操纵)纳入相关漏洞修复总结,与漏洞修复建议相结合,供社区开发者阅读;
- (2)新增技术文章3篇,两名外部人员(360攻防实验室研究员、星澜科技安全研究员)加入贡献;
- (3)“终端安全”版块新增7篇漏洞分析复现文章,新增技术文章5篇(外部来源4篇、内部原创1篇:netlink通信模块研究及利用);
- 已在openKylin社区提交cveissue202个,提供CVE信息、评分、补丁和参考文献等内容。SecurityGovernance共修复85个;
- 新建项目openkylin-cve-tracer用于建设openkylin情报共享机制,并新增项目介绍;
- 新建项目openkylin-cve-manager-bot,用于漏洞信息的自动化流转;
- 漏洞感知大脑项目新增架构图与发布issue流程;
- 安全漏洞扫描框架仓库(genmai)完成优化三个模块功能(沙箱接口模块,YAML配置解析模块,JSON配置解析模块),提交go代码两千多行;
- “诊脉”漏洞检测框架/工具(genmai),编写poc交互解析器、终端文字UI界面,代码量新增一千三百多行;
- 安全治理SIG组自主打补丁83个;
- openKylin社区终端插件仓库(a-cool-config)累计上传三十几个插件,编写两个安装脚本,编写相关的配置使用说明;
- 对openkylin统一用户中心(id.openkylin.top)初步探测,存在文件上传接口未限制上传类型漏洞,可导致攻击者拿到管理员权限,已告知整改。
欢迎所有对openKylin版本安全全漏洞挖掘/验证、安全漏洞修复等安全方面工作感兴趣的社区爱好者加入我们!
十四、UKUIApplications SIG
本SIG组致力于openKylin社区的基础应用开发和维护,扩展openKylin系统的生态。本月主要进展如下:
- 推进0.9版本遗留bug修复;
- 修复安全漏洞 KVE-2022-1103。
欢迎所有对openKylin社区UKUI应用开发工作感兴趣的社区爱好者加入我们!
十五、OpenSDK SIG
本SIG组负责openKylin开发者套件(base、system、applications)规划、开发、维护等工作,致力于解决应用在多操作系统中的兼容性问题。本月主要进展如下:
- 推进0.9版本遗留bug修复;
- 解决因pc文件导致应用引用sdk库失败问题;
- 完善openSDK v2.0开发指南文档;
- 新增完成通知模块;
- 新增多编程语言支持。
欢迎所有对openKylin社区openSDK开发维护工作感兴趣的社区爱好者加入我们!
十六、Connectivity SIG
本SIG组致力于openKylin社区的互联互通基础能力开发与维护。11月主要进展如下:
- 推进0.9版本遗留bug修复。
欢迎所有对openKylin社区互联互通应用及万物互联能力提升工作感兴趣的社区爱好者加入我们!
十七、InputMethod SIG
本SIG组致力于组建输入法开源社区,推进输入法在社区维护。本月主要进展如下:
- 增加禁用输入法的标志位;
- 允许IM module在创建InputContext对象的时候禁用fcitx5提供的得到焦点和失去焦点时虚拟键盘弹出和关闭行为;
- 和fcitx社区讨论QCompleter焦点策略问题,已向Qt社区提交问题issues,同时提供补丁解决方案;
- 推进0.9版本遗留bug。
欢迎所有对openKylin社区fcitx输入法框架、桌面虚拟键盘开发工作感兴趣的社区爱好者加入我们!
关于openKylin社区SIG
openKylin(开放麒麟)社区是一个自由开放的社区,社区中所有的SIG小组都是开放的,任何人和组织都可以参与。你可以选择加入已有SIG,也可以选择创建新的SIG。截至目前,openKylin社区已有56个SIG在运行,包括Architecture、Infrastructure、Release、Kernel、Security、Compatibility等。
如果您对此感兴趣,想要加入openKylin(开放麒麟)社区,参与SIG贡献,可 “https://www.openkylin.top/sig/index-cn.html ” 了解更多详细内容。
关于openKylin社区
openKylin(开放麒麟)社区旨在以“共创”为核心,在开源、自愿、平等、协作的基础上,通过开源、开放的方式与企业构建合作伙伴生态体系,共同打造桌面操作系统顶级社区,推动Linux开源技术及其软硬件生态繁荣发展。
社区首批理事成员单位包括麒麟软件、普华基础软件、中科方德、麒麟信安、凝思软件、一铭软件、中兴新支点、心科技、中国电科32所、技德系统、北京麟卓、先进操作系统创新中心等13家产业同仁和行业机构。
审核:openKyli
2019 年,腾讯低调发布了 Linux 的更新,目前版本停留在 2.0 Beta2。
时隔 3 年, for Linux 基于 NT 技术架构迎来全新升级。今日(12 月 7 日)起,全新 Linux 正式开启公测,版本号为 2.0.1。
下载链接:deb | rpm | AppImage
需要注意的是, for Linux 新版本目前只支持 x64 架构,arm64 架构还在加急适配中。
根据腾讯 项目组的通告,全新的 for Linux 基于 Electron 开发,因此理论上支持所有 Linux 发行版。
Electron 是跨平台的桌面应用开发工具,基于 Electron 构建的应用可同时支持 Linux、Windows 和 Mac。
一张广泛传播的 聊天截图显示,基于 Electron 构建的 还会提供支持 Windows 的版本,并将于明年对外公布。
目前已经推出的 for Mac 新版本也提到了采用全新架构——“NT技术架构”,而 for Mac 新版本正是基于 Electron 构建。
延伸阅读
- 腾讯悄悄发布 Linux ,版本 2.0 Beta
- for Linux 复活,微信 for Linux 还远吗?
1. 用户空间和内核态空间
1.1 为什么要区分用户和内核
服务器大多都采用 Linux 系统,这里我们以 Linux 为例来讲解:
ubuntu 和 Centos 都是 Linux 的发行版,发行版可以看成对 linux 包了一层壳,任何 Linux 发行版,其系统内核都是 Linux 。我们的应用都需要通过 Linux 内核与硬件交互
用户的应用,比如 redis ,mysql 等其实是没有办法去执行访问我们操作系统的硬件的,所以我们可以通过发行版的这个壳子去访问内核,再通过内核去访问计算机硬件
计算机硬件包括,如 cpu,内存,网卡等等,内核(通过寻址空间)可以操作硬件的,但是内核需要不同设备的驱动,有了这些驱动之后,内核就可以去对计算机硬件去进行 内存管理,文件系统的管理,进程的管理等等
我们想要用户的应用来访问,计算机就必须要通过对外暴露的一些接口,才能访问到,从而简介的实现对内核的操控,但是内核本身上来说也是一个应用,所以他本身也需要一些内存,cpu 等设备资源,用户应用本身也在消耗这些资源,如果不加任何限制,用户去操作随意的去操作我们的资源,就有可能导致一些冲突,甚至有可能导致我们的系统出现无法运行的问题,因此我们需要把用户和内核隔离开
1.2 进程寻址空间
进程的寻址空间划分成两部分:内核空间、用户空间
什么是寻址空间呢?我们的应用程序也好,还是内核空间也好,都是没有办法直接去物理内存的,而是通过分配一些虚拟内存映射到物理内存中,我们的内核和应用程序去访问虚拟内存的时候,就需要一个虚拟地址,这个地址是一个无符号的整数。
比如一个 32 位的操作系统,他的带宽就是 32,他的虚拟地址就是 2 的 32 次方,也就是说他寻址的范围就是 0~2 的 32 次方, 这片寻址空间对应的就是 2 的 32 个字节,就是 4GB,这个 4GB,会有 3 个 GB 分给用户空间,会有 1GB 给内核系统
在 linux 中,他们权限分成两个等级,0 和 3,用户空间只能执行受限的命令(Ring3),而且不能直接调用系统资源,必须通过内核提供的接口来访问内核空间可以执行特权命令(Ring0),调用一切系统资源,所以一般情况下,用户的操作是运行在用户空间,而内核运行的数据是在内核空间的,而有的情况下,一个应用程序需要去调用一些特权资源,去调用一些内核空间的操作,所以此时他俩需要在用户态和内核态之间进行切换。
比如:
Linux 系统为了提高 IO 效率,会在用户空间和内核空间都加入缓冲区:
- 写数据时,要把用户缓冲数据拷贝到内核缓冲区,然后写入设备
- 读数据时,要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区
针对这个操作:我们的用户在写读数据时,会去向内核态申请,想要读取内核的数据,而内核数据要去等待驱动程序从硬件上读取数据,当从磁盘上加载到数据之后,内核会将数据写入到内核的缓冲区中,然后再将数据拷贝到用户态的 buffer 中,然后再返回给应用程序,整体而言,速度慢,就是这个原因,为了加速,我们希望 read 也好,还是 wait for data 也最好都不要等待,或者时间尽量的短。
2. 网络模型
2.1 阻塞IO
- 过程 1:应用程序想要去读取数据,他是无法直接去读取磁盘数据的,他需要先到内核里边去等待内核操作硬件拿到数据,这个过程是需要等待的,等到内核从磁盘上把数据加载出来之后,再把这个数据写给用户的缓存区。
- 过程 2:如果是阻塞 IO,那么整个过程中,用户从发起读请求开始,一直到读取到数据,都是一个阻塞状态。
用户去读取数据时,会去先发起 recvform 一个命令,去尝试从内核上加载数据,如果内核没有数据,那么用户就会等待,此时内核会去从硬件上读取数据,内核读取数据之后,会把数据拷贝到用户态,并且返回 ok,整个过程,都是阻塞等待的,这就是阻塞 IO
总结如下:
顾名思义,阻塞 IO 就是两个阶段都必须阻塞等待:
阶段一:
- 用户进程尝试读取数据(比如网卡数据)
- 此时数据尚未到达,内核需要等待数据
- 此时用户进程也处于阻塞状态
阶段二:
- 数据到达并拷贝到内核缓冲区,代表已就绪
- 将内核数据拷贝到用户缓冲区
- 拷贝过程中,用户进程依然阻塞等待
- 拷贝完成,用户进程解除阻塞,处理数据
可以看到,阻塞 IO 模型中,用户进程在两个阶段都是阻塞状态。
2.2 非阻塞 IO
顾名思义,非阻塞 IO 的 recvfrom 操作会立即返回结果而不是阻塞用户进程
阶段一:
- 用户进程尝试读取数据(比如网卡数据)
- 此时数据尚未到达,内核需要等待数据
- 返回异常给用户进程
- 用户进程拿到 error 后,再次尝试读取
- 循环往复,直到数据就绪
阶段二:
- 将内核数据拷贝到用户缓冲区
- 拷贝过程中,用户进程依然阻塞等待
- 拷贝完成,用户进程解除阻塞,处理数据
- 可以看到,非阻塞 IO 模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。虽然是非阻塞,但性能并没有得到提高。而且忙等机制会导致 CPU 空转,CPU 使用率暴增。
2.3 信号驱动
信号驱动 IO 是与内核建立 SIGIO 的信号关联并设置回调,当内核有 FD 就绪时,会发出 SIGIO 信号通知用户,期间用户应用可以执行其它业务,无需阻塞等待。
阶段一:
- 用户进程调用 sigaction ,注册信号处理函数
- 内核返回成功,开始监听 FD
- 用户进程不阻塞等待,可以执行其它业务
- 当内核数据就绪后,回调用户进程的 SIGIO 处理函数
阶段二:
- 收到 SIGIO 回调信号
- 调用 recvfrom ,读取
- 内核将数据拷贝到用户空间
- 用户进程处理数据
当有大量 IO 操作时,信号较多,SIGIO 处理函数不能及时处理可能导致信号队列溢出,而且内核空间与用户空间的频繁信号交互性能也较低。
2.4 异步 IO
这种方式,不仅仅是用户态在试图读取数据后,不阻塞,而且当内核的数据准备完成后,也不会阻塞
他会由内核将所有数据处理完成后,由内核将数据写入到用户态中,然后才算完成,所以性能极高,不会有任何阻塞,全部都由内核完成,可以看到,异步 IO 模型中,用户进程在两个阶段都是非阻塞状态。
2.5 IO 多路复用
场景引入
为了更好的理解 IO ,现在假设这样一种场景:一家餐厅
- A 情况:这家餐厅中现在只有一位服务员,并且采用客户排队点餐的方式,就像这样:
每排到一位客户要吃到饭,都要经过两个步骤:
思考要吃什么 顾客开始点餐,厨师开始炒菜
由于餐厅只有一位服务员,因此一次只能服务一位客户,并且还需要等待当前客户思考出结果,这浪费了后续排队的人非常多的时间,效率极低。这就是阻塞 IO。
当然,为了缓解这种情况,老板完全可以多雇几个人,但这也会增加成本,而在极大客流量的情况下,仍然不会有很高的效率提升
- B 情况: 这家餐厅中现在只有一位服务员,并且采用客户排队点餐的方式。
每排到一位客户要吃到饭,都要经过两个步骤:
- 思考要吃什么
- 顾客开始点餐,厨师开始炒菜
与 A 情况不同的是,此时服务员会不断询问顾客:“你想吃番茄鸡蛋盖浇饭吗?那滑蛋牛肉呢?那肉末茄子呢?……”
虽然服务员在不停的问,但是在网络中,这并不会增加数据的就绪速度,主要还是等顾客自己确定。所以,这并不会提高餐厅的效率,说不定还会招来更多差评。这就是非阻塞 IO。
- C 情况: 这家餐厅中现在只有一位服务员,但是不再采用客户排队的方式,而是顾客自己获取菜单并点餐,点完后通知服务员,就像这样:
每排到一位客户要吃到饭,还是都要经过两个步骤:
- 看着菜单,思考要吃什么
- 通知服务员,我点好了
与 A B 不同的是,这种情况服务员不必再等待顾客思考吃什么,只需要在收到顾客通知后,去接收菜单就好。这样相当于餐厅在只有一个服务员的情况下,同时服务了多个人,而不像 A B,同一时刻只能服务一个人。此时餐厅的效率自然就提高了很多。
映射到我们的网络服务中,就是这样:
- 客人:客户端请求
- 点餐内容:客户端发送的实际数据
- 老板:操作系统
- 人力成本:系统资源
- 菜单:文件状态描述符。操作系统对于一个进程能够同时持有的文件状态描述符的个数是有限制的,在 linux 系统中 $ulimit -n 查看这个限制值,当然也是可以 (并且应该) 进行内核参数调整的。
- 服务员:操作系统内核用于 IO 操作的线程 (内核线程)
- 厨师:应用程序线程 (当然厨房就是应用程序进程咯)
- 餐单传递方式:包括了阻塞式和非阻塞式两种。
- 方法 A: 阻塞 IO
- 方法 B: 非阻塞 IO
- 方法 C: 多路复用 IO
2.6 多路复用 IO 的实现
目前流程的多路复用 IO 实现主要包括四种: select、poll、epoll、kqueue。下表是他们的一些重要特性的比较:
多路复用 IO 技术最适用的是 “高并发” 场景,所谓高并发是指 1 毫秒内至少同时有上千个连接请求准备好。其他情况下多路复用 IO 技术发挥不出来它的优势。另一方面,使用 JAVA NIO 进行功能实现,相对于传统的 Socket 套接字实现要复杂一些,所以实际应用中,需要根据自己的业务需求进行技术选择。
2.6.1 select
select 是 Linux 最早是由的 I/O 多路复用技术:
linux 中,一切皆文件,socket 也不例外,我们把需要处理的数据封装成 FD,然后在用户态时创建一个 fd_set 的集合(这个集合的大小是要监听的那个 FD 的最大值 + 1,但是大小整体是有限制的 ),这个集合的长度大小是有限制的,同时在这个集合中,标明出来我们要控制哪些数据。
其内部流程:
用户态下:
- 创建 fd_set 集合,包括要监听的 读事件、写事件、异常事件 的集合
- 确定要监听的 fd_set 集合
- 将要监听的集合作为参数传入 select () 函数中,select 中会将 集合复制到内核 buffer 中
内核态:
- 内核线程在得到 集合后,遍历该集合
- 没数据就绪,就休眠
- 当数据来时,线程被唤醒,然后再次遍历集合,标记就绪的 fd 然后将整个集合,复制回用户 buffer 中
- 用户线程遍历 集合,找到就绪的 fd ,再发起读请求。
不足之处:
- 集合大小固定为 1024 ,也就是说最多维持 1024 个 socket,在海量数据下,不够用
- 集合需要在 用户 buffer 和内核 buffer 中反复复制,涉及到 用户态和内核态的切换,非常影响性能
2.6.2 poll
poll 模式对 select 模式做了简单改进,但性能提升不明显。
IO 流程:
- 创建 pollfd 数组,向其中添加关注的 fd 信息,数组大小自定义
- 调用 poll 函数,将 pollfd 数组拷贝到内核空间,转链表存储,无上限
- 内核遍历 fd ,判断是否就绪
- 数据就绪或超时后,拷贝 pollfd 数组到用户空间,返回就绪 fd 数量 n
- 用户进程判断 n 是否大于 0, 大于 0 则遍历 pollfd 数组,找到就绪的 fd
与 select 对比:
- select 模式中的 fd_set 大小固定为 1024,而 pollfd 在内核中采用链表,理论上无上限,但实际上不能这么做,因为的监听 FD 越多,每次遍历消耗时间也越久,性能反而会下降
2.6.3 epoll
epoll 模式是对 select 和 poll 的改进,它提供了三个函数:eventpoll 、epoll_ctl 、epoll_wait
- eventpoll 函数内部包含了两个东西 :
- 红黑树 :用来记录所有的 fd
- 链表 : 记录已就绪的 fd
- epoll_ctl 函数 ,将要监听的 fd 添加到 红黑树 上去,并且给每个 fd 绑定一个监听函数,当 fd 就绪时就会被触发,这个监听函数的操作就是 将这个 fd 添加到 链表中去。
- epoll_wait 函数,就绪等待。一开始,用户态 buffer 中创建一个空的 events 数组,当就绪之后,我们的回调函数会把 fd 添加到链表中去,当函数被调用的时候,会去检查链表(当然这个过程需要参考配置的等待时间,可以等一定时间,也可以一直等),如果链表中没有有 fd 则 fd 会从红黑树被添加到链表中,此时再将链表中的的 fd 复制到 用户态的空 events 中,并且返回对应的操作数量,用户态此时收到响应后,会从 events 中拿到已经准备好的数据,在调用 读方法 去拿数据。
2.6.4 总结:
select 模式存在的三个问题:
- 能监听的 FD 最大不超过 1024
- 每次 select 都需要把所有要监听的 FD 都拷贝到内核空间
- 每次都要遍历所有 FD 来判断就绪状态
poll 模式的问题:
- poll 利用链表解决了 select 中监听 FD 上限的问题,但依然要遍历所有 FD,如果监听较多,性能会下降
epoll 模式中如何解决这些问题的?
- 基于 epoll 实例中的红黑树保存要监听的 FD,理论上无上限,而且增删改查效率都非常高
- 每个 FD 只需要执行一次 epoll_ctl 添加到红黑树,以后每次 epol_wait 无需传递任何参数,无需重复拷贝 FD 到内核空间
- 利用 ep_poll_callback 机制来监听 FD 状态,无需遍历所有 FD,因此性能不会随监听的 FD 数量增多而下降
2.7 基于 epoll 的服务器端流程
一张图搞定:
我们来梳理一下这张图
- 服务器启动以后,服务端会去调用 epoll_create,创建一个 epoll 实例,epoll 实例中包含两个数据
-
红黑树(为空):rb_root 用来去记录需要被监听的 FD
-
链表(为空):list_head,用来存放已经就绪的 FD
-
创建好了之后,会去调用 epoll_ctl 函数,此函数会会将需要监听的 fd 添加到 rb_root 中去,并且对当前这些存在于红黑树的节点设置回调函数。
-
当这些被监听的 fd 一旦准备就绪,与之相关联的回调函数就会被调用,而调用的结果就是将红黑树的 fd 添加到 list_head 中去 (但是此时并没有完成)
-
fd 添加完成后,就会调用 epoll_wait 函数,这个函数会去校验是否有 fd 准备就绪(因为 fd 一旦准备就绪,就会被回调函数添加到 list_head 中),在等待了一段时间 (可以进行配置)。
-
如果等够了超时时间,则返回没有数据,如果有,则进一步判断当前是什么事件,如果是建立连接事件,则调用 accept () 接受客户端 socket ,拿到建立连接的 socket ,然后建立起来连接,如果是其他事件,则把数据进行写出。
2.8 五种网络模型对比:
最后用一幅图,来说明他们之间的区别
3. redis 通信协议
3.1 RESP 协议
Redis 是一个 CS 架构的软件,通信一般分两步(不包括 pipeline 和 PubSub):
- 客户端(client)向服务端(server)发送一条命令,服务端解析并执行命令
- 返回响应结果给客户端,因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通信协议。
而在 Redis 中采用的是 RESP(Redis Serialization Protocol)协议:
- Redis 1.2 版本引入了 RESP 协议
- Redis 2.0 版本中成为与 Redis 服务端通信的标准,称为 RESP2
- Redis 6.0 版本中,从 RESP2 升级到了 RESP3 协议,增加了更多数据类型并且支持 6.0 的新特性–客户端缓存
但目前,默认使用的依然是 RESP2 协议。在 RESP 中,通过首字节的字符来区分不同数据类型,常用的数据类型包括 5 种:
- 单行字符串:首字节是 ‘+’ ,后面跟上单行字符串,以 CRLF( “ ” )结尾。例如返回”OK”: “+OK ”
- 错误(Errors):首字节是 ‘-’ ,与单行字符串格式一样,只是字符串是异常信息,例如:”-Error message ”
- 数值:首字节是 ‘:’ ,后面跟上数字格式的字符串,以 CRLF 结尾。例如:”:10 ”
- 多行字符串:首字节是 ‘$’ ,表示二进制安全的字符串,最大支持 512MB:
- 如果大小为 0,则代表空字符串:”$0 ”
- 如果大小为 – 1,则代表不存在:”$-1 ”
- 数组:首字节是 ‘*’,后面跟上数组素个数,再跟上素,素数据类型不限 :
本文由教研团队发布。
如果本文对您有帮助,欢迎和;如果您有任何建议也可或,您的支持是我坚持创作的动力。
转载请注明出处!
摘要:本篇文章将分享图像分类原理,并介绍基于KNN、朴素贝叶斯算法的图像分类案例。
本文分享自华为云社区《[Python图像处理] 二十六.图像分类原理及基于KNN、朴素贝叶斯算法的图像分类案例丨【百变AI秀】》,作者:eastmount 。
一.图像分类
图像分类(Image Classification)是对图像内容进行分类的问题,它利用计算机对图像进行定量分析,把图像或图像中的区域划分为若干个类别,以代替人的视觉判断。图像分类的传统方法是特征描述及检测,这类传统方法可能对于一些简单的图像分类是有效的,但由于实际情况非常复杂,传统的分类方法不堪重负。现在,广泛使用机器学习和深度学习的方法来处理图像分类问题,其主要任务是给定一堆输入图片,将其指派到一个已知的混合类别中的某个标签。
在下图中,图像分类模型将获取单个图像,并将为4个标签{cat,dog,hat,mug},分别对应概率{0.6, 0.3, 0.05, 0.05},其中0.6表示图像标签为猫的概率,其余类比。该图像被表示为一个三维数组。在这个例子中,猫的图像宽度为248像素,高度为400像素,并具有红绿蓝三个颜色通道(通常称为RGB)。因此,图像由248×400×3个数字组成或总共个数字,每个数字是一个从0(黑色)到255(白色)的整数。图像分类的任务是将这接近30万个数字变成一个单一的标签,如“猫(cat)”。
那么,如何编写一个图像分类的算法呢?又怎么从众多图像中识别出猫呢?这里所采取的方法和教育小孩看图识物类似,给出很多图像数据,让模型不断去学习每个类的特征。在训练之前,首先需要对训练集的图像进行分类标注,如图所示,包括cat、dog、mug和hat四类。在实际工程中,可能有成千上万类别的物体,每个类别都会有上百万张图像。
图像分类是输入一堆图像的像素值数组,然后给它分配一个分类标签,通过训练学习来建立算法模型,接着使用该模型进行图像分类预测,具体流程如下:
- 输入: 输入包含N个图像的集合,每个图像的标签是K种分类标签中的一种,这个集合称为训练集。
- 学习: 第二步任务是使用训练集来学习每个类的特征,构建训练分类器或者分类模型。
- 评价: 通过分类器来预测新输入图像的分类标签,并以此来评价分类器的质量。通过分类器预测的标签和图像真正的分类标签对比,从而评价分类算法的好坏。如果分类器预测的分类标签和图像真正的分类标签一致,表示预测正确,否则预测错误。
二.常见分类算法
常见的分类算法包括朴素贝叶斯分类器、决策树、K最近邻分类算法、支持向量机、神经网络和基于规则的分类算法等,同时还有用于组合单一类方法的集成学习算法,如Bagging和Boosting等。
1.朴素贝叶斯分类算法
朴素贝叶斯分类(Naive Bayes Classifier)发源于古典数学理论,利用Bayes定理来预测一个未知类别的样本属于各个类别的可能性,选择其中可能性最大的一个类别作为该样本的最终类别。在朴素贝叶斯分类模型中,它将为每一个类别的特征向量建立服从正态分布的函数,给定训练数据,算法将会估计每一个类别的向量均值和方差矩阵,然后根据这些进行预测。
朴素贝叶斯分类模型的正式定义如下:
该算法的特点为:如果没有很多数据,该模型会比很多复杂的模型获得更好的性能,因为复杂的模型用了太多假设,以致产生欠拟合。
2.KNN分类算法
K最近邻分类(K-Nearest Neighbor Classifier)算法是一种基于实例的分类方法,是数据挖掘分类技术中最简单常用的方法之一。该算法的核心思想如下:一个样本x与样本集中的k个最相邻的样本中的大多数属于某一个类别yLabel,那么该样本x也属于类别yLabel,并具有这个类别样本的特性。
简而言之,一个样本与数据集中的k个最相邻样本中的大多数的类别相同。由其思想可以看出,KNN是通过测量不同特征值之间的距离进行分类,而且在决策样本类别时,只参考样本周围k个“邻居”样本的所属类别。因此比较适合处理样本集存在较多重叠的场景,主要用于预测分析、文本分类、降维等处理。
该算法在建立训练集时,就要确定训练数据及其对应的类别标签;然后把待分类的测试数据与训练集数据依次进行特征比较,从训练集中挑选出最相近的k个数据,这k个数据中投票最多的分类,即为新样本的类别。KNN分类算法的流程描述为如下图所示。
该算法的特点为:简单有效,但因为需要存储所有的训练集,占用很大内存,速度相对较慢,使用该方法前通常训练集需要进行降维处理。
3.SVM分类算法
支持向量机(Support Vector Machine)是数学家Vapnik等人根据统计学习理论提出的一种新的学习方法,其基本模型定义为特征空间上间隔最大的线性分类器,其学习策略是间隔最大化,最终转换为一个凸二次规划问题的求解。SVM分类算法基于核函数把特征向量映射到高维空间,建立一个线性判别函数,解最优在某种意义上是两类中距离分割面最近的特征向量和分割面的距离最大化。离分割面最近的特征向量被称为“支持向量”,即其它向量不影响分割面。图像分类中的SVM如下图所示,将图像划分为不同类别。
下面的例子可以让读者对SVM快速建立一个认知。给定训练样本,支持向量机建立一个超平面作为决策曲面,使得正例和反例的隔离边界最大化。决策曲面的构建过程如下所示:
- 在下图中,想象红球和蓝球为球台上的桌球,首先需要找到一条曲线将蓝球和红球分开,于是得到一条黑色的曲线。
- 为了使黑色曲线离任意的蓝球和红球距离最大化,我们需要找到一条最优的曲线,如下图所示。
- 假设这些球不是在球桌上,而是抛在空中,但仍然需要将红球和蓝球分开,这时就需要一个曲面,而且该曲面仍然满足所有任意红球和蓝球的间距最大化,如图16-7所示。离这个曲面最近的红色球和蓝色球就被称为“支持向量(Support Vector)”。
该算法的特点为:当数据集比较小的时候,支持向量机的效果非常好。同时,SVM分类算法较好地解决了非线性、高维数、局部极小点等问题,维数大于样本数时仍然有效。
4.随机森林分类算法
随机森林(Random Forest)是用随机的方式建立一个森林,在森林里有很多决策树的组成,并且每一棵决策树之间是没有关联的。当有一个新样本出现的时候,通过森林中的每一棵决策树分别进行判断,看看这个样本属于哪一类,然后用投票的方式,决定哪一类被选择的多,并作为最终的分类结果。
随机森林中的每一个决策树“种植”和“生长”主要包括以下四个步骤:
- 假设训练集中的样本个数为N,通过有重置的重复多次抽样获取这N个样本,抽样结果将作为生成决策树的训练集;
- 如果有M个输入变量,每个节点都将随机选择m(m<M)个特定的变量,然后运用这m个变量来确定最佳的分裂点。在决策树的生成过程中,m值是保持不变的;
- 每棵决策树都最大可能地进行生长而不进行剪枝;
- 通过对所有的决策树进行加来预测新的数据(在分类时采用多数投票,在回归时采用平均)。
该算法的特点为:在分类和回归分析中都表现良好;对高维数据的处理能力强,可以处理成千上万的输入变量,也是一个非常不错的降维方法;能够输出特征的重要程度,能有效地处理缺省值。
5.神经网络分类算法
神经网络(Neural Network)是对非线性可分数据的分类方法,通常包括输入层、隐藏层和输出层。其中,与输入直接相连的称为隐藏层(Hidden Layer),与输出直接相连的称为输出层(Output Layer)。神经网络算法的特点是有比较多的局部最优值,可通过多次随机设定初始值并运行梯度下降算法获得最优值。图像分类中使用最广泛的是BP神经网络和CNN神经网络。
BP神经网络
BP神经网络是一种多层的前馈神经网络,其主要的特点为:信号是前向传播的,而误差是反向传播的。BP神经网络的过程主要分为两个阶段,第一阶段是信号的前向传播,从输入层经过隐含层,最后到达输出层;第二阶段是误差的反向传播,从输出层到隐含层,最后到输入层,依次调节隐含层到输出层的权重和偏置,输入层到隐含层的权重和偏置,具体结构如下图所示。
神经网络的基本组成单是神经。神经的通用模型如图所示,其中常用的激活函数有阈值函数、Sigmoid函数和双曲正切函数等。
CNN卷积神经网络
卷积神经网络(Convolutional Neural Networks)是一类包含卷积计算且具有深度结构的前馈神经网络,是深度学习的代表算法之一。卷积神经网络的研究始于二十世纪80至90年代,时间延迟网络和LeNet-5是最早出现的卷积神经网络。在二十一世纪后,随着深度学习理论的提出和数值计算设备的改进,卷积神经网络得到了快速发展,并被大量应用于计算机视觉、自然语言处理等领域。
三.基于KNN算法的图像分类
1.KNN算法
K最近邻分类(K-Nearest Neighbor Classifier)算法是一种基于实例的分类方法,是数据挖掘分类技术中最简单常用的方法之一。该算法的核心思想是从训练样本中寻找所有训练样本X中与测试样本距离(欧氏距离)最近的前K个样本(作为相似度),再选择与待分类样本距离最小的K个样本作为X的K个最邻近,并检测这K个样本大部分属于哪一类样本,则认为这个测试样本类别属于这一类样本。
假设现在需要判断下图中的圆形图案属于三角形还是正方形类别,采用KNN算法分析如下:
- 当K=3时,图中第一个圈包含了三个图形,其中三角形2个,正方形一个,该圆的则分类结果为三角形。
- 当K=5时,第二个圈中包含了5个图形,三角形2个,正方形3个,则以3:2的投票结果预测圆为正方形类标。设置不同的K值,可能预测得到不同的结果。
简而言之,一个样本与数据集中的k个最相邻样本中的大多数的类别相同。由其思想可以看出,KNN是通过测量不同特征值之间的距离进行分类,而且在决策样本类别时,只参考样本周围k个“邻居”样本的所属类别。因此比较适合处理样本集存在较多重叠的场景,主要用于预测分析、文本分类、降维等处理。
KNN在Sklearn机器学习包中,实现的类是neighbors.KNeighborsClassifier,简称KNN算法。构造方法为:
KNeighborsClassifier可以设置3种算法:brute、kd_tree、ball_tree,设置K值参数为n_neighbors=3。调用方法如下:
- from sklearn.neighbors import KNeighborsClassifier
- knn = KNeighborsClassifier(n_neighbors=3, algorithm=“ball_tree”)
它包括两个步骤:
- 训练:nbrs.fit(data, target)
- 预测:pre = clf.predict(data)
2.数据集
该部分主要使用Scikit-Learn包进行Python图像分类处理。Scikit-Learn扩展包是用于Python数据挖掘和数据分析的经典、实用扩展包,通常缩写为Sklearn。Scikit-Learn中的机器学习模型是非常丰富的,包括线性回归、决策树、SVM、KMeans、KNN、PCA等等,用户可以根据具体分析问题的类型选择该扩展包的合适模型,从而进行数据分析,其安装过程主要通过“pip install scikit-learn”实现。
实验所采用的数据集为Sort_1000pics数据集,该数据集包含了1000张图片,总共分为10大类,分别是人(第0类)、沙滩(第1类)、建筑(第2类)、大卡车(第3类)、恐龙(第4类)、大象(第5类)、花朵(第6类)、马(第7类)、山峰(第8类)和食品(第9类),每类100张。如图所示。
接着将所有各类图像按照对应的类标划分至“0”至“9”命名的文件夹中,如图所示,每个文件夹中均包含了100张图像,对应同一类别。
比如,文件夹名称为“6”中包含了100张花的图像,如下图所示。
3.KNN图像分类
下面是调用KNN算法进行图像分类的完整代码,它将1000张图像按照训练集为70%,测试集为30%的比例随机划分,再获取每张图像的像素直方图,根据像素的特征分布情况进行图像分类分析。KNeighborsClassifier()核心代码如下:
- from sklearn.neighbors import KNeighborsClassifier
- clf = KNeighborsClassifier(n_neighbors=11).fit(XX_train, y_train)
- predictions_labels = clf.predict(XX_test)
完整代码及注释如下:
代码中对预测集的前十张图像进行了显示,其中“818.jpg”图像如图所示,其分类预测的类标结果为“8”,表示第8类山峰,预测结果正确。
下图展示了“452.jpg”图像,其分类预测的类标结果为“4”,表示第4类恐龙,预测结果正确。
下图展示了“507.jpg”图像,其分类预测的类标结果为“7”,错误地预测为第7类恐龙,其真实结果应该是第5类大象。
使用KNN算法进行图像分类实验,最后算法评价的准确率(Precision)、召回率(Recall)和F值(F1-score)如图所示,其中平均准确率为0.64,平均召回率为0.55,平均F值为0.50,其结果不是非常理想。那么,如果采用CNN卷积神经网络进行分类,通过不断学习细节是否能提高准确度呢?
四.基于朴素贝叶斯算法的图像分类
下面是调用朴素贝叶斯算法进行图像分类的完整代码,调用sklearn.naive_bayes中的BernoulliNB()函数进行实验。它将1000张图像按照训练集为70%,测试集为30%的比例随机划分,再获取每张图像的像素直方图,根据像素的特征分布情况进行图像分类分析。
代码中对预测集的前十张图像进行了显示,其中“368.jpg”图像如下图所示,其分类预测的类标结果为“3”,表示第3类大卡车,预测结果正确。
下图展示了“452.jpg”图像,其分类预测的类标结果为“4”,表示第4类恐龙,预测结果正确。
使用朴素贝叶斯算法进行图像分类实验,最后预测的结果及算法评价准确率(Precision)、召回率(Recall)和F值(F1-score)如图所示。
五.总结
本篇文章主要讲解Python环境下的图像分类算法,首先普及了常见的分类算法,包括朴素贝叶斯、KNN、SVM、随机森林、神经网络等,接着通过朴素贝叶斯和KNN分别实现了1000张图像的图像分类实验,希望对读者有一定帮助,也希望这些知识点为读者从事Python图像处理相关项目实践或科学研究提供一定基础。
参考文献:
[1]冈萨雷斯著. 数字图像处理(第3版)[M]. 北京:电子工业出版社,2013.
[2]杨秀璋, 颜娜. Python网络数据爬取及分析从入门到精通(分析篇)[M]. 北京:北京航天航空大学出版社, 2018.
[3]gzq0723. 干货——图像分类(上)[EB/OL]. (2018-08-28). https://blog.csdn.net/gzq0723/
[4]article/details/.
[5]sinat_. OpenCV分类器学习心得[EB/OL]. (2016-08-03). https://blog.csdn.net/sinat_/article/details/.
[6]baidu_. 机器学习之贝叶斯算法图像分类[EB/OL]. (2018-10-10). https://blog.csdn.net/baidu_/article/details/.
[7]baidu_. 机器学习之KNN算法实现图像分类[EB/OL]. (2018-09-28). https://blog.csdn.net/baidu_/article/details/.
[8]normol. svm实现图片分类(python)[EB/OL]. (2018-11-19). https://blog.csdn.net/normol/article/details/.
[9]wfjiang. SVM-支持向量机原理详解与实践[EB/OL]. (2017-03-14). https://www.cnblogs.com/spoorer/p/6551220.html.
[10]快乐的小飞熊. 随机森林原理[EB/OL]. (2017-03-05). https://www.sigusoft.com/p/57e862d695f2.
[11]烨枫_邱. 深入理解BP神经网络[EB/OL]. (2018-06-01). https://www.sigusoft.com/p/6ab6f53874f7.
[12]smilejiasmile. 卷积神经网络(CNN)及其实践[EB/OL]. (2018-06-20). https://blog.csdn.net/smilejiasmile/article/details/.
[13] 誓天断发. 机器学习之BP神经网络算法实现图像分类[EB/OL]. (2018-10-23). https://blog.csdn.net/baidu_/article/details/.
[14] 杨秀璋. [Python人工智能] 十.Tensorflow+Opencv实现CNN自定义图像分类案例及与机器学习KNN图像分类算法对比[EB/OL]. https://blog.csdn.net/Eastmount/article/details/.
关注,第一时间了解华为云新鲜技术~
从2014年 Forrester Research 首次提出“低代码开发平台(LCAP)”这一概念开始,低代码行业便备受关注。随着 SaaS 场景的加持,aPaaS 场景也被孵化了出来。与此同时,随着近两年 Outsystems 的快速发展,让其成为一方独角兽的同时,也加速了低代码行业的进一步发展。
2022年12月1日,为进一步推进低代码/无代码技术的应用与发展,企业数字化发展共建共享平台、云计算标准和开源推进委员会(CCSA TC608)联合云智慧等企业及专家举办了“低代码/无代码应用深度探索系列沙龙”。本期沙龙中,云智慧生动形象地讲解了低代码平台在公司内部的落地实践,帮助企业及开发者更好地理解研发设计、企业协同、流程治理、数字化大屏、运维管理等众多场景低代码/无代码化。
理解企业现状痛点,推进低代码落地
云智慧专注于数据可视化大屏业务,通过将电商、金融等各行业数据与内部系统接入后,以大屏的形式简洁、快速地呈现出来。当前低代码数据可视化行业主要存在以下痛点:
-
技术栈太多:正常前端页面编写仅需用到 UI 框架等简单技术栈,而在可视化方面开发人员会用到很多可视化相关的技术栈,包括 图表相关的 Highcharts、Echarts、D3 等技术栈;关系图、系统架构图以及网络链路图相关的 G6、Vis 等技术栈;3D 可视化相关的 Three、WebGL等技术栈。
-
架构复杂:数据可视化大屏的制作过程并非是各技术栈的堆砌,而是需从系统兼容性以及多端适配优化处理等方面考虑,将各技术进行有效结合。
-
部署复杂:以单纯业务方面部署为例(如Docker、K8S等),企业开发人员需做 Ngnix代理、网管、注册中心、缓存等方面的管理。
除上述外,对于企业低代码开发人员来讲,一方面日常工作需应对频繁变更的需求;另一方面还需面对性能兼容、高可用、国际化等方面的高复杂性;此外,还需应对技术栈、版本更新以及人员整体能力等多方面的持续变化。与此同时,对于企业来讲,一方面因企业没有统一低代码基础平台,导致大量工作重复从而开发造成人员浪费;此外,企业产品系统开发过于依赖开发人员的习惯,导致数据复用性较差以及开发质量无法保证;同时,在产品系统开发过程中,因大量简单基础的工作需要重复完成,导致降低开发效率。
低代码赋能企业,促进企业发展
云智慧作为低代码专业厂商,通过低代码为各大企业带来全新产品供给模式的同时,使各大企业更容易获得全方位的生态解决方案。此外,低代码作为效率工具,加速推进了企业数字化进程同时使企业实现规模化发展。具体主要体现在以下几方面:
-
增效:可视化变成所见即所得,一站式开发无需搭建环境,通过拖拉拽的形式快速生成一整套解决方案。
-
高质量:开箱即用的高质量组件,同一套规则、同一套标准,经过多轮测试验证发版,稳定可靠。
-
可复用:从原本一锤子的买卖,变成可以沉淀的资产,组件之间可以复用,数据方向可以规范标准,复用性强。
-
低门槛:由于低代码开发的特征,大大降低了开发的难度,使其可以非常快速搭建一套解决方案,无代码基础也可快速上手。
简洁高效,加速开发者成长
低代码作为一种全新的开发模式,相比于传统开发模式,低代码很大程度地减少了开发者代码量,使开发者通过简单地复刻及拖拉拽即可完成应用开发。另一方面,由于低代码的简单直观性,开发者也更容易发现技术应用业务过程中的问题。因此低代码更能加快开发者在技术领域的成长速度,具体表现为以下几方面:
开箱即用:云智慧低代码平台 FlyFish 通过内置多化开箱即用的数据可视化组件,使开发者可以通过拖拉拽的方式即可快速使用组件、模版完成数据可视化大屏制作。
随时随地:无需安装各类插件,云智慧在线低代码平台使开发者随时随地可开发所需数据可视化大屏。
能力复用:云智慧在线低代码平台使开发者可以看到代码配置详情,可快速进行能力复用。
减少发布流程:低代码往往作为一个aPaaS 应用,一定程度上可以省略发布流程。
新一代开发模式,云智慧 FlyFish
飞鱼平台 (FlyFish) 是云智慧公司自主设计、研发的一款低门槛、高拓展性的低代码应用开发平台,为数据可视化开发场景提供了高效的一站式解决方案。飞鱼提供丰富的组件和应用模板库,可通过拖拉拽的形式完成数据可视化开发,零开发背景的用户也可完成数据可视化开发工作。
FlyFish 整体架构如下图所示。组件与组件之间相互隔离,且通过Event调度中心与函数进行交互。数据源接入系统后,可以被封装成数据集合被大屏调用。此外,FlyFish 在渲染处理、兼容处理、通信处理、动效处理以及性能处理方面均做了优化。
云智慧在 FlyFish 的开发应用过程中成功沉淀了近千张大屏模版以及2500+应用组件。此外,FlyFish 在云智慧的整体业务应用流程中,使其效率得到了有效提升。至今,除开发人员外,云智慧内部已有30%的人员通过FlyFish开发出数据可视化大屏供个人工作所需。
最后
低代码/无代码技术作为新一代开发模式,现已成为赋能企业数字化发展转型的加速器。现如今,云智慧数据可视化编排平台 FlyFish 已开源,感兴趣的伙伴可下方链接查看详情。未来,云智慧也将联合更多企业联盟不断完善低代码应用建设,为各行业企业生态发展注入生命力。
GitHub 地址: https://github.com/CloudWise-OpenSource/FlyFish
Gitee 地址: https://gitee.com/CloudWise/fly-fish
本文转载自阿里云Hologres产品负责人合一在ITPUB的访谈,谈谈他眼中的实时数仓
这两年,企业IT领域掀起实时数仓热潮。然而,只要稍做梳理就会发现,实时数仓格局未定,各种流派群雄逐鹿,还有很多需要进一步探讨的话题方向。
比如:实时数仓是什么?如何从概念上去定义?有人认为,传统数据仓库做了实时化,就是实时数仓;有人认为,云数仓、湖仓一体是实时数仓;还有人认为,HTAP是解决实时数仓需求的一个重要手段!
再比如:实时数仓是一款产品,还是一个解决方案?99%的企业都会认为是一个解决方案,1%的企业会认为是一款产品,这1%就是阿里云!
为了弄清事实真相,帮助用户找到应用选型“快速通道”,本期实时数仓系列访谈,特邀请到阿里云自研大数据平台产品负责人刘一鸣(合一),请他从实时数仓的技术演进、应用场景、架构以及Hologres自身实践角度,一层一层揭开实时数仓的“谜团”!
阿里云自研大数据平台产品负责人刘一鸣(合一)
实时数仓进化
如果,非要给实时数仓下一个定义,一定要符合从1.0到3.0时代的进化特征。
首先,得是一个数仓,具备规模数据的交互式分析能力。实时数仓不只是“实时”,很多系统不支持标准SQL,不能算数仓。所以,属于1.0时代的实时数仓,有一个重要前提,就是支持较为完善的SQL以及优秀的大规模分析能力,因此很多系统采用了分布式、列存、索引、压缩等数仓加速的技术。
其次,面向实时场景做了针对性优化,包括实时写入、实时分析、实时取数等。如果和普通数据库相同,没有针对实时场景做优化,很难达到实时数仓对吞吐和分析的时效性要求。实时数仓需要具备高吞吐写入和更新能力,数据写入即可用,支持灵活的数据更新。比如:很多普通数据库,虽然能写也能查,但当数据规模放大到一定规模,要么牺牲了写入性能保查询,要么牺牲了查询性能优化写入,无法针对实时数据多场景进行优化,这不能算好的实时数仓。
进入2.0时代,实时数仓就要尽可能快地支持在线业务。企业之所以做实时数仓,是希望数据进来之后能够被足够新鲜地消费,能实时写入、实时分析,还要支撑在线服务。在线服务场景需要更高的性能、低抖动、稳定性、并发能力,对在线服务场景进行支持,是实时数仓关键一环。
而3.0时代的实时数仓,可以定义为一站式实时数仓。这个时候的实时数仓,不仅具有高吞吐写入与更新、端到端的全链路实时加工以及低延迟高并发在线服务能力,在保证数据一致的前提下,需要支持多种负载之间完备的隔离和弹性能力,以确保各个业务互不干扰,各自按需使用资源。同时实时数仓的使用通常离不开离线数仓的组合关系,通过离线平台对历史数据的周期性汇聚、抽象和加工,并将结果数据导入实时数仓进行丰富和修正,需要更有效地打通实时与离线两套系统,实现数据和数据的无缝交换,这也是实时数仓落地时需要具备的能力。这种一站式体现在存储状态的一致性,减少了不同负载之间的数据同步和存储开销,避免了数据服务层的数据孤岛难题。
所以,实时数仓既不是传统数据库的旧瓶装新酒,也不是湖仓一体的多产品组合,它和离线数仓的本质区别是,通过对易变数据结构(包括内存结构、文件存储)和计算资源的细粒度灵活管控,更好地支撑数据的实时写入、实时更新、实时查询 。 至于,很多公司之所以把实时数仓定义为是一个解决方案,是因为技术相对更加复杂,既要考虑写入和加工能力,又要支持查询和在线分析场景,不得已针对不同技术需求将多种技术栈堆砌在一起,包括采用流式计算、消息中间件来达到端到端的实时加工,采用列式数据库应对分析需求,采用行存系统支撑在线服务系统,并依赖复杂的调度配置,实现数据在中间件、存储系统之间的最终一致性。而将复杂技术落地成为一款易于使用的成熟数仓产品,仍然是少数技术创新者在努力的方向。
阿里云Hologres,整体技术水平领先业界1-2年,是基于在阿里巴巴内部数据技术的广泛应用与沉淀,一步一步走过来的。阿里有海量数据的复杂应用场景,有历年双11等大促的深度压力测试,有在存储和计算领域深扎多年的技术专家,有上万名数据小二支持业务的灵活需求与快速迭代,这些都是其他公司不具备的得天独厚的条件,推动着阿里在数据技术领域的持续创新。
Hologres支撑的业务的规模、复杂性和对效率的极致追求,实现了通过有些开源技术组合无法达成的数据价值目标。行业内不少企业采用部分开源技术栈,如:用Kafka做中间件,用Hudi做离线存储,用Presto做离线查询加速,用ClickHouse做OLAP查询,用Flink做流式数据加工,用MySQL做缓存,用HBase做在线服务引擎。这些架构也是阿里采用过的第一代实时数仓架构,但当开发效率遇到瓶颈时,当数据链路复杂到成为运维负担时,当数据不一致不得不80%时间在对数排查时,工程师们开始思考是否还有更好的解决方案,是否有一个更加集中化、一体化、能力更全面的数仓选择。而Hologres的出现也就重新定义了实时数仓的形态。
基于此,OLAP查询和在线服务使用Hologres,满足分析的灵活和效率,离线数仓使用MaxCompute,支撑规模性和Serverless扩展性,实时流式计算用Flink,凸显端到端全实时加工,三者的结合让实时和离线计算,分析和服务都能达到一个非常好的平衡,满足业务的多种需求。
阿里云Flink版的出处与Hologres的渊源
有人可能会说,阿里云Hologres+Flink这套组合也用了Flink,和其他解决方案相比,有什么不同呢?
没错,Hologres要想发挥最佳水平,与Flink结合,一定是首选。实时计算需要后台有一套强大的大数据计算能力,而Apache Flink作为一款开源大数据流式计算技术,从设计之初就由流计算开启,相比传统的Hadoop、Spark等计算引擎,更能确保数据处理的低延时,让数据在第一时间发挥价值。
早在2016年,Apache Flink捐献给Apache之后的第三年,阿里已经开始大规模上线使用实时计算产品,用于阿里最核心的搜索推荐以及广告业务场景。2017年,基于Flink的实时计算产品,开始服务于整个阿里巴巴集团,同年双11服务全集团的数据实时化,包括双11的实时大屏。2018年,基于Flink的实时计算平台产品不仅服务于集团内部,同时开始服务于云上中小企业,以公有云的形式对外提供服务。2019年,阿里巴巴收购了Flink的创始公司-Ververica,阿里的Flink实时计算技术团队和德国总部的Flink创始团队,组成全球顶领先的Flink技术团队,共同推进整个Apache Flink开源社区的发展。
用户通过Flink可以把数据实时写入到Hologres,也可以通过Hologres做维表关联。如此一来,离线分析走MaxCompute,数据的点查、联邦分析以及OLAP分析走Hologres。举一个维表加工的例子,Flink每次加工进来之后,每一条事件都要跟维表做关联,比如:事件数据中包含了渠道ID,在分析时需要知道是什么渠道类型,因为要通过加工链路将ID还原为渠道属性,这种关联有时候每秒钟要达到上万、上十万的 QPS。过去,很多业务团队采用HBase来支撑这类点查业务,但HBase没有 Schema,数据写错很难发现,很难修正;现在,Hologres只用过去50% 的资源,支撑了HBase完整的业务。
与开源Flink相比,阿里的实时计算Flink版进行了多处核心功能的优化,在存储、网络和传输等方面都调整到满足业务场景所需要的效果。并且,阿里云Flink版和Hologres做了大量的结合优化工作,不仅支持维表到结果表,也支持通过阿里云Flink的全量读取、Binlog 读取、CDC 读取、全增量一体化等多种方式读取 Hologres 源表数据,尤其是阿里云Flink支持读取Hologres Binlog,就使得Hologres能够达到像Kafka等消息中间件同等的能力,一个 Hologres Table 的数据既可以提供给下游阿里云 Flink 任务消费,还可以对接上游 OLAP/在线服务查询,不仅节省了成本,还简化数仓架构,同时也让数仓中的每一个层次都可以实时构建、实时查询,提升数据的流转效率。在数据管理方面,阿里云Flink版与Hologres数据打通,支持Hologres Catalog,实现数据的自动发现和管理,也大大简化了开发和运维管理工作。
HSAP分析服务一体化的独特之处
Hologres是两个英文单词的组合,即Holographic+Postgres,Holographic来源于物理学,Postgres代表的是PostgreSQL生态。
从物理学原理看,地球没有被黑洞吸进去,是因为有一个临界点,这个临界点所组成的面,被证明是一个球面,也叫世界面。与此同时,黑洞里所有信息在世界面上都有投影,即3D全息投影技术。Hologres想做的事情是,通过产品化的能力对数据黑洞做全息展示。
为了简化数据存储和统一数据服务,阿里云提出了HSAP架构理论 (Hybrid Serving & Analytical Processing,后续简称HSAP),而Hologres是实践HSAP目标的一个具体实现。Hologres的目标是,做分析服务一体化的实时数仓,典型特征是:存算分离的云原生架构、多负载隔离、端到端实时毫秒级的交互式分析体验、超高QPS的在线服务能力等。从应用场景来看,既可满足实时数仓的需求,也能对离线数据进行查询加速,同时还可实现实时与离线数据的联邦计算,为用户构筑全链路、精细化运营能力。
为什么说分析服务一体化能力特别重要呢?
以广告推荐为例,这是一个非常典型的在线服务场景,如果一个人收藏了一个链接,他就会获得相应的广告推荐,该推荐包含了你过去30 天、60天或者90 天里的行为,还包括你的教育程度、家庭关系,这些是典型的离线特征。对于后端技术平台来说,这些行为不用每天去算,每周算一次就可以。但另一部分特征是实时的,比如你当下点了什么内容,对什么感兴趣,跳转了什么链接,这部分行为就需要通过Flink 这样的流式计算实时处理。只有把实时和离线两部分信息结合起来做推荐,才有全面的360信息,使得推荐更加精准,更加具备上下文相关性。
过去,没有Hologres之前,如果一个大数据系统要支撑广告推荐业务需要写一条很长的链路,反复同步数据,这很难提供灵活敏捷的数据服务,大量数据作业开发成本很高,出现数据不一致等问题。阿里的工程师尝试把问题简化,让数据不动,通过Flink或者MaxCompute加工好的数据,直接提供在线服务,这就需要把Serving场景做强,面向应用程序,或者面向API 消费数据的场景时,要有高QPS、低延迟能力。
而针对Analytics能力,很多企业都会基于OLAP引擎做数据分析。这部分数据一般会有两个出口:一个出口是给机器使用,通过API访问,主要是推荐系统和风控系统;另一个出口是给分析师使用,通过SQL访问,看报表,做对比分析,找到趋势变化。这两个出口的数据需要保持一致性。Hologres作为交互式分析引擎,针对两个场景做了执行优化。在支持在线的高 QPS 服务型查询时,这类查询逻辑相对简单,但并发高,因此采用了Short-Cut技术,通过FixedPlan执行优化,减少在SQL解析优化和调度层的开销,请求直达存储节点,延迟更短;在支持分析师的复杂多维分析时,采用MPP分布式计算框架、列式存储和向量化引擎,有效率大范围过滤数据,保障了亿级数据的秒级数据分析。这样,通过Hologres统一数据服务出口,同时支持在线服务和多维分析两个场景。
Hologres借鉴了主流的数据架构,包括采用类似LSM-tree(Log-Structured Merge Tree)这种高吞吐写入和更新友好的存储架构,利用了CPU指令向量化、异步化的最新技术创新,基于云原生的计算存储分离架构,形成了一款低门槛的生产级产品。Hologres在协议层面上用到了PostgreSQL的这种协议,简化了与业务系统的对接,应用无需重写,也没有厂商引擎绑定,开箱即用,核心的存储引擎、查询引擎是阿里自研的一套系统,持续改进效率、稳定和易用。
Lambda 与Kappa的纷争
其实,最早阿里云没想到要做实时数仓,只是想把实时和离线数据实现一体化。
换言之,阿里云的HSAP架构也是由Lambda架构走过来的。众所周知,Lambda架构有一个优势,既支持流式数仓,又能满足离线数仓的计算要求;但是也有一个弊端,就是流和批分为两套技术栈,运维要维护两套系统架构。后来,Kappa架构出现,有人认为能很好地解决Lambda架构的问题,但事实并非如此。因为企业的数据加工永远会有实时和离线两条链路,这是数据加工作业的属性决定的。实时链路数据总会晚来,或者不来,数据质量并不可靠。所以,只有实时链路,解决不了数据质量问题,还需要离线链路对实时链路的修正和丰富,而依赖消息中间件支撑海量数据的回刷是成本极高及不稳定的架构。也就是说,只要有离线场景,Lambda架构就有存在的合理性。
但问题是,Lambda架构一定需要两套系统,这该如何解决?本质上,还是技术的割裂,导致架构不统一。好的Lambda架构,应该是状态层统一的,实时的业务逻辑和离线的业务逻辑尽管加工链路不同,但存储层应该统一,减少数据割裂和不一致,通过实时和离线两套业务逻辑相互补充,离线的业务逻辑对实时数据链路进行修正。
在Lambda架构实践过程中,很多企业实时业务用HBase,离线业务用Hive,这种存储割裂状态,导致数据不一致,口径不一致。正确的架构选择应该是Lambda的改进版,把数据状态统一存储在一个存储系统,这个存储同时支持离线批量导入,也支持实时更新与查询,这也是一种可落地的批流一体实践。
虽然,有些企业在推Kappa,但从实践的角度看,Kappa其实是个伪概念,因为实时业务系统如果取代离线,意味着数据要频繁地修正、更新,而Kappa无法从根本上解决这个问题。目前,推Kappa架构的企业,大部分是消息中间件厂商,或者一些纯粹做实时的团队。他们假设了一种状态,所有的数据都可以通过消息中间件恢复。但现实是,企业不会把所有的状态都通过消息中间件去回放,或者长期存储。所以,通过消息中间件替代数据库的方式,只有消息中间件厂商在力推,不具备广泛落地的参考意义。
在阿里内部,HSAP架构把分析和服务两个场景放在一起,解决了数据不一致问题,减少了数据同步的开销,避免了数据孤岛,数据加工链路保持了实时和离线双链路,实时业务系统解决时效性问题,离线可以为实时业务系统进行修正和丰富,两条链路各解决各自的问题,使得实时和离线由一套系统承载,也就真正实现了流批一体。
下一代实时数仓更重实操
到今天为止,Hologres作为标准产品对外提供服务已经两年多,每年客户数都是三位数增长。在实践中,60%的用户主要使用OLAP场景,20%主要使用Serving场景,还有20%做到了HSAP混合负载的优化架构,通过技术创新为企业降本提效。实时数仓还处于发展过程中,相信随着大数据的不断推动,实时数仓会成为推动业务发展的“有力抓手”。
过去,数据团队更偏内部业务场景,主要的工作就是给管理层出报表,做领导驾驶舱。但在今天,数据团队正从成本中心转为盈利中心,大数据团队要想去影响业务,提升价值感,包括风控、实时画像、实时推荐等手段,是提升业务的主要入口,这也是实时数仓需求快速增长的最根本原因。实时数仓会成为大数据平台里一个重要组成部分,是数据消费端的核心组件。
当然,实时数仓并不是一个新事物,从有数仓开始,用户需求一直存在。但是,因为方案的不成熟,很多都是由开源组件堆在一起,从开发和运维成本上看,技术门槛比较高,导致实时数仓没有实现规模化发展。企业必须招聘来自BAT的人才才能玩得转实时数仓,这个是不正常的,也不是时代发展的趋势,技术一定会普惠化,所有的企业都会用上大数据,但不应该所有的企业都成为技术专家。
真正受市场欢迎的实时数仓产品,简单、易用是前提,能处理海量数据,不用懂很多参数,不用写很多程序,能做到只会写SQL就可以上手。另外,企业希望数据写进来就能用,尽量减少数据加工过程,减少数据链条,实现敏捷化。即使业务方突然提出一个新需求,只要改下SQL就可以了,不用做任何数据重刷,对开发效率提升来说,带来的是根本性的转变。
所以,下一代实时数仓到底如何发展? Hologres已经“打好样”!那就是技术门槛会越来越低,同时计算力会越来越强大,使用方式越来越简单,不仅数据能实时写得进来,还要在原始数据上直接做分析,查询要足够快,并发足够高,取数不用等,需求不求人。希望通过Hologres这样的产品,能够将实时数仓变得更加普惠化、敏捷化,让各行各业的数智化建设迈上新台阶。
亲爱的社区小伙伴们,经历数月的等候,我们很高兴地宣布,Apache Doris 于 2022 年 12 月 7 日迎来了 1.2.0 Release 版本的正式发布!有近 118 位 Contributor 为 Apache Doris 提交了超 2400 项优化和修复,感谢每一位让 Apache Doris 更好的你!
自从社区正式确立 LTS 版本管理机制后,在 1.1.x 系列版本中不再合入大的功能,仅提供问题修复和稳定性改进,力求满足更多社区用户在稳定性方面的高要求。而综合考虑版本迭代节奏和用户需求后,我们决定将众多新特性在 1.2.0 版本中发布,这无疑承载了众多社区用户和开发者的深切期盼,同时也是一场厚积而薄发后的全面进化!
在 1.2 版本中,我们实现了全面向量化、实现多场景查询性能3-11 倍的提升,在 Unique Key 模型上实现了 Merge-on-Write 的数据更新模式、数据高频更新时查询性能提升达 3-6 倍,增加了 Multi-Catalog 多源数据目录、提供了无缝接入 Hive、ES、Hudi、Iceberg 等外部数据源的能力,引入了 Light Schema Change 轻量表结构变更、实现毫秒级的 Schema Change 操作并且可以借助 Flink CDC 自动同步上游数据库的 DML 和 DDL 操作,以 JDBC 外部表替换了过去的 ODBC 外部表,支持了 Java UDF 和 Romote UDF 以及 Array 数组类型和 JSONB 类型,修复了诸多之前版本的性能和稳定性问题,推荐大家下载和使用!
下载安装
GitHub下载: https://github.com/apache/doris/releases
官网下载页: https://doris.apache.org/download
源码地址: https://github.com/apache/doris/releases/tag/1.2.0-rc04
下载说明
由于 Apache 服务器对文件大小限制,官网下载页的 1.2.0 版本的二进制程序分为三个包:
- apache-doris-fe
- apache-doris-be
- apache-doris-java-udf-jar-with-dependencies
其中新增的包用于支持 1.2 版本中的 JDBC 外表和 JAVA UDF 新功能。下载后需要将其文件放到 目录下,方可启动 BE,否则无法启动成功。
为了便于大家下载使用,我们将预编译好的二进制程序提前打包好,该版本基于 Apache Doris 1.2.0 正式版,仅内置了 java8 运行时环境,复制下方链接到浏览器下载,解压后即可使用。
下载链接:
- ARM64:https://selectdb-doris-.cos.ap-beijing.myqcloud.com/release/selectdb-doris-1.2.0-arm.tar.gz
- x86:https://selectdb-doris-.cos.ap-beijing.myqcloud.com/release/selectdb-doris-1.2.0-x86_64-no-avx2.tar.gz
- x86_no_avx2:https://selectdb-doris-.cos.ap-beijing.myqcloud.com/release/selectdb-doris-1.2.0-x86_64-no-avx2.tar.gz
部署说明
从历史版本升级到 1.2.0 版本,需完整更新 fe、be 下的 bin 和 lib 目录。
其他升级注意事项,请完整阅读以下文档:
- 本通告最后一节「升级注意事项」
- 安装部署文档:https://doris.apache.org/zh-CN/docs/dev/install/install-deploy
- 集群升级文档:https://doris.apache.org/zh-CN/docs/dev/admin-manual/cluster-management/upgrade
如在版本升级、功能验证、生产上线等过程中出现问题,可以在社区用户群中寻求 SelectDB 专职技术工程师帮助。
重要更新
全面向量化支持,性能大幅提升
在 Apache Doris 1.2.0 版本中,系统所有模块都实现了向量化,包括数据导入、Schema Change、Compaction、数据导出、UDF 等。新版向量化执行引擎具备了完整替换原有非向量化引擎的能力,后续我们也将考虑在未来版本中去除原有非向量化引擎的代码。
与此同时,在全面向量化的基础上,我们对数据扫描、谓词计算、Aggregation 算子、HashJoin 算子、算子之间 Shuffle 效率等进行了全链路的优化,使得查询性能有了大幅提升。
我们对 Apache Doris 1.2.0 新版本进行了多个标准测试集的测试,同时选择了 1.1.3 版本和 0.15.0 版本作为对比参照项。经测,1.2.0 在 SSB-Flat 宽表场景上相对 1.1.3 版本整体性能提升了近 4 倍、相对于 0.15.0 版本性能提升了近 10 倍,在 TPC-H 多表关联场景上较 1.1.3 版本上有近 3 倍的提升、较 0.15.0 版本性能至少提升了 11 倍。
图1 SSB
图2 TPC-H
同时,我们将1.2.0版本的测试数据提交到了全球知名数据库测试排行榜 ClickBench,在最新的排行榜中,Apache Doris 1.2.0 新版本取得了通用机型(c6a.4xlarge, 500gb gp2)下查询性能 Cold Run 第二和 Hot Run 第三的醒目成绩,共有 8 个 SQL 刷新榜单最佳成绩、成为新的性能标杆。 导入性能方面,1.2.0 新版本数据写入效率在同机型所有产品中位列第一,压缩前 70G 数据写入仅耗时 415s、单节点写入速度超过 170 MB/s,在实现极致查询性能的同时也保证了高效的写入效率!
图3 Cold Run
图4 Hot Run
UniqueKey 模型实现 Merg-On-Write 数据更新模式
在过去版本中, Apache Doris 主要是通过 Unique Key 数据模型来实现数据实时更新的。但由于采用的是 Merge-On-Read 的实现方式,查询存在着效率瓶颈,有大量非必要的 CPU 计算资源消耗和 IO 开销,且可能将出现查询性能抖动等问题。
在 1.2.0 版本中,我们在原有的 Unique Key 数据模型上,增加了 Merge-On-Write 的数据更新模式。 该模式在数据写入时即对需要删除或更新的数据进行标记,始终保证有效的主键只出现在一个文件中(即在写入的时候保证了主键的唯一性),不需要在读取的时候通过归并排序来对主键进行去重,这对于高频写入的场景来说,大大减少了查询执行时的额外消耗。此外还能够支持谓词下推,并能够很好利用 Doris 丰富的索引,在数据 IO 层面就能够进行充分的数据裁剪,大大减少数据的读取量和计算量,因此在很多场景的查询中都有非常明显的性能提升。
在比较有代表性的 SSB-Flat 数据集上,通过模拟多个持续导入场景,新版本的大部分查询取得了 3-6 倍的性能提升。
- 使用场景: 所有对主键唯一性有需求,需要频繁进行实时 Upsert 更新的用户建议打开。
- 使用说明: 作为新的 Feature 默认关闭,用户可以通过在建表时添加下面的 Property 来开启:
另外新版本 Merge-On-Write 数据更新模式与旧版本 Merge-On-Read 实现方式存在差异,因此已经创建的 Unique Key 表无法直接通过 Alter Table 添加 Property 来支持,只能在新建表的时候指定。如果用户需要将旧表转换到新表,可以使用的方式来实现。
Multi Catalog 多源数据目录
Multi-Catalog 多源数据目录功能的目标在于能够帮助用户更方便对接外部数据目录,以增强 Apache Doris 的数据湖分析和联邦数据查询能力。
在过去版本中,当我们需要对接外部数据源时,只能在 Database 或 Table 层级对接。当外部数据目录 Schema 发生变化、或者外部数据目录的 Database 或 Table 非常多时,需要用户手工进行一一映射,维护量非常大。1.2.0 版本新增的多源数据目录功能为 Apache Doris 提供了快速接入外部数据源进行访问的能力,用户可以通过命令连接到外部数据源,Doris 会自动映射外部数据源的库、表信息。之后,用户就可以像访问普通表一样,对这些外部数据源中的数据进行访问,避免了之前用户需要对每张表手动建立外表映射的复杂操作。
目前能支持以下数据源:
- Hive Metastore:可以访问包括 Hive、Iceberg、Hudi 在内的数据表,也可对接兼容 Hive Metastore 的数据源,如阿里云的 DataLake Formation,同时支持 HDFS 和对象存储上的数据访问。
- Elasticsearch:访问 ES 数据源。
- JDBC:支持通过 JDBC 访问 MySQL 数据源。
注:相应的权限层级也会自动变更,详见「升级注意事项」部分
相关文档:
https://doris.apache.org/zh-CN/docs/dev/ecosystem/external-table/multi-catalog
轻量表结构变更 Light Schema Change
在过去版本中,SchemaChange是一项相对消耗比较大的工作,需要对数据文件进行修改,在集群规模和表数据量较大时执行效率会明显降低。同时由于是异步作业,当上游Schema发生变更时,需要停止数据同步任务并手动执行SchemaChange,增加开发和运维成本的同时还可能造成消费数据的积压。
在 1.2.0 新版本中,对数据表的加减列操作,不再需要同步更改数据文件,仅需在 FE 中更新数据即可,从而实现毫秒级的 Schema Change 操作,且存在导入任务时效率的提升更为显著。 与此同时,使得 Apache Doris 在面对上游数据表维度变化时,可以更加快速稳定实现表结构同步,保证系统的高效且平稳运转。如用户可以通过 Flink CDC,可实现上游数据库到 Doris 的 DML 和 DDL 同步,进一步提升了实时数仓数据处理和分析链路的时效性与便捷性。
使用说明: 作为新的 Feature 默认关闭,用户可以通过在建表时添加下面的 Property 来开启:
相关文档:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-TABLE
JDBC 外部表
在过去版本中,Apache Doris 提供了 ODBC 外部表的方式来访问 MySQL、Oracle、SQL Server、PostgreSQL 等数据源,但由于 ODBC 驱动版本问题可能造成系统的不稳定。相对于 ODBC,JDBC 接口更为统一且支持数据库众多,因此在 1.2.0 版本中我们实现了 JDBC 外部表以替换原有的 ODBC 外部表。在新版本中,用户可以通过 JDBC 连接支持 JDBC 协议的外部数据源,当* 前已适配的数据源包括*:
- MySQL
- PostgreSQL
- Oracle
- SQLServer
- ClickHouse
更多数据源的适配已经在规划之中,原则上任何支持 JDBC 协议访问的数据库均能通过 JDBC 外部表的方式来访问。而之前的 ODBC 外部表功能将会在后续的某个版本中移除,还请尽量切换到 JDBC 外表功能。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/ecosystem/external-table/jdbc-of-doris/
JAVA UDF
在过去版本中,Apache Doris 提供了 C++ 语言的原生 UDF,便于用户通过自己编写自定义函数来满足特定场景的分析需求。但由于原生 UDF 与 Doris 代码耦合度高、当 UDF 出现错误时可能会影响集群稳定性,且只支持 C++ 语言,对于熟悉 Hive、Spark 等大数据技术栈的用户而言存在较高门槛,因此在 1.2.0 新版本我们增加了 Java 语言的自定义函数,支持通过 Java 编写 UDF/UDAF,方便用户在 Java 生态中使用。同时,通过堆外内存、Zero Copy 等技术,使得跨语言的数据访问效率大幅提升。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/ecosystem/udf/java-user-defined-function
示例:
https://github.com/apache/doris/tree/master/samples/doris-demo
Remote UDF
远程 UDF 支持通过 RPC 的方式访问远程用户自定义函数服务,从而彻底消除用户编写 UDF 的语言限制,用户可以使用任意编程语言实现自定义函数,完成复杂的数据分析工作。
相关文档:
https://doris.apache.org/zh-CN/docs/ecosystem/udf/remote-user-defined-function
示例:
https://github.com/apache/doris/tree/master/samples/doris-demo
Array/JSONB 复合数据类型
Array 类型
支持了数组类型,同时也支持多级嵌套的数组类型。在一些用户画像,标签等场景,可以利用 Array 类型更好的适配业务场景。同时在新版本中,我们也实现了大量数组相关的函数,以更好的支持该数据类型在实际场景中的应用。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Types/ARRAY
相关函数:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-functions/array-functions/array
JSONB 类型
支持二进制的 JSON 数据类型 JSONB。该类型提供更紧凑的 JSONB 编码格式,同时提供在编码格式上的数据访问,相比于使用字符串存储的 JSON 数据,有数倍的性能提升。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Types/JSONB
相关函数:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-functions/json-functions/jsonb_parse
DateV2/DatatimeV2 新版日期/日期时间数据类型
支持 DataV2 日期类型和 DatatimeV2 日期时间类型,相较于原有的 Data 和 Datatime 效率更高且支持最多到微秒的时间精度,建议使用新版日期类型。
相关文档:
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Types/DATETIMEV2/
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Types/DATEV2
影响范围:
- 用户需要在建表时指定 DateV2 和 DatetimeV2,原有表的 Date 以及 Datetime 不受影响。
- Datev2 和 Datetimev2 在与原来的 Date 和 Datetime 做计算时(例如等值连接),原有类型会被cast 成新类型做计算
- Example 相关文档中说明
全新内存管理框架
在 Apache Doris 1.2.0 版本中我们增加了全新的内存跟踪器(Memory Tracker),用以记录 Doris BE 进程内存使用,包括查询、导入、Compaction、Schema Change 等任务生命周期中使用的内存以及各项缓存。通过 Memory Tracker 实现了更加精细的内存监控和控制,大大减少了因内存超限导致的 OOM 问题,使系统稳定性进一步得到提升。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/admin-manual/maint-monitor/memory-management/memory-tracker
Table Valued Function 表函数
增加了 Table Valued Function(TVF,表函数),TVF 可以视作一张普通的表,可以出现在 SQL 中所有“表”可以出现的位置,让用户像访问关系表格式数据一样,读取或访问来自 HDFS 或 S3 上的文件内容,
例如使用 S3 TVF 实现对象存储上的数据导入:
或者直接查询 HDFS 上的数据文件:
TVF 可以帮助用户充分利用 SQL 丰富的表达能力,灵活处理各类数据。
相关文档:
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-functions/table-functions/s3
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-functions/table-functions/hdfs
更多功能
1. 更便捷的分区创建方式
支持通过命令创建一个时间范围内的多个分区。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-TABLE
示例:
2. 列重命名
对于开启了 Light Schema Change 的表,支持对列进行重命名。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Alter/ALTER-TABLE-RENAME
3. 更丰富的权限管理
- 支持行级权限。可以通过 命令创建行级权限。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-POLICY
- 支持指定密码强度、过期时间等。
- 支持在多次失败登录后锁定账户。相关文档: https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Account-Management-Statements/ALTER-USER
4. 导入相关
- CSV 导入支持带 Header 的 CSV 文件。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/Load/STREAM-LOAD/
- Stream Load 新增 ,可以显式指定 Deleteflag 列和 Sequence列。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/Load/STREAM-LOAD
- Spark Load 支持 Parquet 和 ORC 文件导入。
- 支持清理已完成的导入的 Label。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/Load/CLEAN-LABEL
- 支持通过状态批量取消导入作业。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/Load/CANCEL-LOAD
- Broker Load 新增支持阿里云 OSS,腾讯 CHDFS 和华为云 OBS。相关* 文档*:https://doris.apache.org/zh-CN/docs/dev/advanced/broker
- 支持通过 hive-site.xml 文件配置访问 HDFS。相关* 文档*:https://doris.apache.org/zh-CN/docs/dev/admin-manual/config/config-dir
5. 支持通过SHOW CATALOG RECYCLE BIN功能查看回收站中的内容。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Show-Statements/SHOW-CATALOG-RECYCLE-BIN
6. 支持语法
相关文档:
https://doris.apache.org/zh-CN/docs/dev/data-table/basic-usage
7. OUTFILE 支持 ORC 格式导出,并且支持多字节分隔符
相关文档:
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/OUTFILE
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/OUTFILE
8. 支持通过配置修改可保存的 Query Profile 的数量。
文档搜索 FE 配置项:max_query_profile_num
9.DELETE语句支持IN谓词条件,并且支持分区裁剪。
相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Manipulation-Statements/Manipulation/DELETE
10. 时间列的默认值支持使用
相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-TABLE
11. 添加两张系统表:backends、rowsets
backends 是 Doris 中内置系统表,存放在 information_schema 数据库下,通过该系统表可以查看当前 Doris 集群中的 BE 节点信息。
rowsets 是 Doris 中内置系统表,存放在 数据库下,通过该系统表可以查看 Doris 集群中各个 BE 节点当前 rowsets 情况。
相关文档:
- https://doris.apache.org/zh-CN/docs/dev/admin-manual/system-table/backends
- https://doris.apache.org/zh-CN/docs/dev/admin-manual/system-table/rowsets
12. 备份恢复
- Restore作业支持 参数,使得恢复后的表的副本数和备份时一致。
- Restore 作业支持参数,使得恢复后的表保持动态分区开启状态。相关* *文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Backup-and-Restore/RESTORE
- 支持通过内置的Libhdfs 进行备份恢复操作,不再依赖 Broker。相关文档: https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Backup-and-Restore/CREATE-REPOSITORY
13. 支持同机多磁盘之间的数据均衡
相关文档:
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-REBALANCE-DISK
- https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-CANCEL-REBALANCE-DISK
14. Routine Load 支持订阅 Kerberos 认证的 Kafka 服务。
相关文档:
https://doris.apache.org/zh-CN/docs/dev/data-operate/import/import-way/routine-load-manual
15. New built-in-function 新增内置函数
新增以下内置函数:
-
cbrt
-
sequence_match/sequence_count
-
mask/mask_first_n/mask_last_n
-
elt
-
any/any_value
-
group_bitmap_xor
-
ntile
-
nvl
-
uuid
-
initcap
-
regexp_replace_one/regexp_extract_all
-
multi_search_all_positions/multi_match_any
-
domain/domain_without_www/protocol
-
running_difference
-
bitmap_hash64
-
murmur_hash3_64
-
to_monday
-
not_null_or_empty
-
window_funnel
-
outer combine
-
以及所有 Array 函数
升级注意事项
FE 数据版本变更 【重要】
FE Meta Version 由 107 变更为 114,因此从 1.1.x 以及更早版本升级至 1.2.0 版本后,不可回滚到之前版本。
升级过程中,建议通过灰度升级的方式,先升级部分节点并观察业务运行情况,以降低升级风险,若执行非法的回滚操作将可能导致数据丢失与损坏。
行为改变
- 权限层级变更,因为引入了 Catalog 层级,所以相应的用户权限层级也会自动变更。规则如下:
-
- GlobalPrivs 和 ResourcePrivs 保持不变
- 新增 CatalogPrivs 层级。
- 原 DatabasePrivs 层级增加 internal 前缀(表示 internal catalog 中的 db)
- 原 TablePrivs 层级增加 internal 前缀(表示internal catalog中的 tbl)
- GroupBy 和 Having 子句中,优先使用列名而不是别名进行匹配。
- 不再支持创建以 “mv ” 开头的列。”mv” 是物化视图中的保留关键词
- 移除了 orderby 语句默认添加的 65535 行的 Limit 限制,并增加 Session 变量可以自定配置这个限制。
- “Create Table As Select” 生成的表,所有字符串列统一使用 String 类型,不再区分 varchar/char/string
- audit log 中,移除 db 和 user 名称前的字样。
- audit log 中增加 sql digest 字段
- union 子句总 order by 逻辑变动。新版本中,order by 子句将在 union 执行完成后执行,除非通过括号进行显式的关联。
- 进行 Decommission 操作时,会忽略回收站中的 Tablet,确保 Decomission 能够完成。
- Decimal 的返回结果将按照原始列中声明的精度进行显示 ,或者按照显式指定的 Cast 函数中的精度进行展示。
- 列名的长度限制由 64 变更为 256
- FE 配置项变动
-
- 默认开启参数。
- 增大了 值。建表操作的默认超时时间将增大。
- 修改 默认值为 3天。
- 修改的默认值为 一个月。
- 增加参数 用于限制 alter 作业中涉及的 Replica 数量,默认为 。
- 添加 。默认禁用了 Iceberg 和 Hudi 外表,推荐使用 Multi Catalog功能。
- BE 配置项变动
-
- 移除了 参数。2PC的 Stream Load 可直接使用。
- 修改从 1800 秒修改为 300 秒。
- Session 变量变动
-
- 修改变量默认为 true。这会导致一些之前可以执行,但是插入了非法值的 insert 操作,不再能够执行。
- 修改变量默认为 true
- 默认通过 lz4 压缩进行数据传输,通过变量 控制
- 增加 变量,用于调试 Unique 或 Agg 模型的数据。 相关* *文档:https://doris.apache.org/zh-CN/docs/dev/advanced/variables
- BE 启动脚本会通过 检查数值是否大于200W,否则启动失败。
- 移除了 mini load 接口
升级过程需注意
升级准备
- 需替换:lib, bin 目录(start/stop 脚本均有修改)
- BE 也需要配置,已支持 JDBC Table 和 Java UDF。
- 中默认参数修改为 8GB。
升级过程中可能的错误
- Repeat 函数不可使用并报错:,可以在升级前先关闭向量化执行引擎。
- Schema Change 失败并报错:desc_tbl is not set. Maybe the FE version is not equal to the BE
- 向量化 Hash Join 不可使用并报错。vectorized hash join cannot be executed可以在升级前先关闭向量化执行引擎。
以上错误在完全升级后会恢复正常。
性能影响
- 默认使用 JeMalloc 作为新版本 BE 的内存分配器,替换 TcMalloc 。JeMalloc 相比 TcMalloc 使用的内存更少、高并发场景性能更高,但在内存充足的性能测试时,TcMalloc 比 JeMalloc 性能高5%-10%,详细测试见: https://github.com/apache/doris/pull/12496
- 中 修改为至少 8K。
- 默认关闭 Page Cache 和 减少 Chunk Allocator 预留内存大小。
Page Cache 和 Chunk Allocator 分别缓存用户数据块和内存预分配,这两个功能会占用一定比例的内存并且不会释放。由于这部分内存占用无法灵活调配,导致在某些场景下可能因这部分内存占用而导致其他任务内存不足,影响系统稳定性和可用性,因此新版本中默认关闭了这两个功能。
但在某些延迟敏感的报表场景下,关闭该功能可能会导致查询延迟增加。如用户担心升级后该功能对业务造成影响,可以通过在 中增加以下参数以保持和之前版本行为一致。
API 变化
- BE 的 HTTP API 错误返回信息,由变更为更具体的{“status”:”Notfound”,”msg”:”Tabletnotfound.tablet_id=1202″}
- 中, Comment 的内容由双引号包裹变为单引号包裹
- 支持普通用户通过 HTTP 命令获取 Query Profile。相关文档:https://doris.apache.org/zh-CN/docs/dev/admin-manual/http-actions/fe/manager/query-profile-action
- 优化了 Sequence 列的指定方式,可以直接指定列名。相关文档:https://doris.apache.org/zh-CN/docs/dev/data-operate/update-delete/sequence-column-manual
- 和返回结果中,增加远端存储的空间使用情况
- 移除了 Num-Based Compaction 相关代码
- 重构了BE的错误码机制,部分返回的错误信息会发生变化
其他
- 支持 Docker 官方镜像。
- 支持在 MacOS(x86/M1) 和 ubuntu-22.04 上编译 Doris。
- 支持进行 image 文件的校验。相关文档:https://doris.apache.org/zh-CN/docs/dev/admin-manual/maint-monitor/metadata-operation
- 脚本相关
-
- FE、BE 的 stop 脚本支持通过参数退出FE、BE(使用 kill -15 信号代替 kill -9)
- FE start 脚本支持通过 查看当前FE 版本
- 支持通过 ADMIN COPY TABLET命令获取某个 tablet 的数据和相关建表语句,用于本地问题调试。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Database-Administration-Statements/ADMIN-COPY-TABLET
- 支持通过 http api,获取一个SQL语句相关的建表语句,用于本地问题复现。相关文档:https://doris.apache.org/zh-CN/docs/dev/admin-manual/http-actions/fe/query-schema-action
- 支持建表时关闭此表的 Compaction 功能,用于测试。相关文档:https://doris.apache.org/zh-CN/docs/dev/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-TABLE
致谢
Apache Doris 1.2.0 版本的发布离不开所有社区用户的支持,在此向所有参与版本设计、开发、测试、讨论的社区贡献者们表示感谢,他们分别是(首字母排序):
贡献者名单
@
@aliou
@adonis0147
@Aiden-Dong
@aiwenmo
@AshinGau
@b19mud
@BePPPower
@BiteTheDDDDt
@bridgeDream
@ByteYue
@caiconghui
@CalvinKirs
@cambyzju
@caoliang-web
@carlvinhust2012
@catpineapple
@ccoffline
@chenlinzhong
@chovy-3012
@coderjiang
@cxzl25
@dataalive
@dataroaring
@dependabot
@dinggege1024
@DongLiang-0
@Doris-Extras
@eldenmoon
@EmmyMiao87
@englefly
@FreeOnePlus
@Gabriel39
@gaodayue
@geniusjoe
@gj-zhang
@gnehil
@GoGoWen
@HappenLee
@hello-stephen
@Henry2SS
@hf
@huyuanfeng2018
@jacktengg
@jackwener
@jeffreys-cat
@Jibing-Li
@JNSimba
@Kikyou1997
@Lchangliang
@LemonLiTree
@lexoning
@liaoxin01
@lide-reed
@link3280
@liutang123
@liuyaolin
@LOVEGISER
@lsy3993
@luozenglin
@luzhijing
@madongz
@morningman
@morningman-cmy
@morrySnow
@mrhhsg
@Myasuka
@myfjdthink
@nextdreamblue
@pan3793
@pangzhili
@pengxiangyu
@platoneko
@qidaye
@qzsee
@SaintBacchus
@SeekingYang
@smallhibiscus
@sohardforaname
@song7788q
@spaces-X
@ssusieee
@stalary
@starocean999
@SWJTU-ZhangLei
@TaoZex
@timelxy
@Wahno
@wangbo
@wangshuo128
@wangyf0555
@weizhengte
@weizuo93
@wsjz
@wunan1210
@xhmz
@xiaokang
@xiaokangguo
@xinyiZzz
@xy720
@yangzhg
@Yankee24
@yeyudefeng
@yiguolei
@yinzhijian
@yixiutt
@yuanyuan8983
@zbtzbtzbt
@zenoyang
@zhangboya1
@zhangstar333
@zhannngchen
@ZHbamboo
@zhengshiJ
@zhenhb
@zhqu
@zuochunwei
@zy-kkk
— END —
最后,欢迎更多的开源技术爱好者加入 Apache Doris 社区,携手成长,共建社区生态。Apache Doris 社区当前已容纳了上万名开发者和使用者,承载了 30+ 交流社群,如果你也是 Apache Doris 的爱好者,扫码加入 Apache Doris 社区用户交流群,在这里你可以获得:
- 专业全职团队技术支持
- 直接和社区专家交流,获取免费且专业回复
- 认识不同行业的开发者,收获知识以及合作机会
- Apache Doris 最新版本优先体验权
- 获取一手干货和资讯以及活动优先参与权
更新内容:
1,应用绑定默认https域名
2,ssl证书管理
3,可根据服务器筛选发布记录
4,应用配置UI优化
BUG修复:
1,新建项目/应用后,导航栏未立即显示,需刷新页面
2,应用首次选择设定发布目录后,没有立即显示,需刷新页面
3,用户编辑资料页无法打开
4,应用在线编辑器,高度未自适应
网址:https://www.oauthapp.com/
文档:https://web.oauthapp.com/4/docs
漏洞描述
TensorFlow 是一个用于机器学习的开源平台。
受影响版本的 TensorFlow 中由于 MakeGrapplerFunctionItem 函数采用固定大小的输入和输出参数,导致用户的输入大于或等于输出的大小时存在越界写入漏洞,攻击者可利用此漏洞造成程序拒绝服务。
影响范围
tensorflow-cpu@[2.10.0, 2.10.1)
tensorflow-gpu@(-∞, 2.8.4)
tensorflow-gpu@[2.10.0, 2.10.1)
tensorflow@[2.9.0, 2.9.3)
tensorflow@[2.10.0, 2.10.1)
tensorflow-cpu@[2.9.0, 2.9.3)
tensorflow-cpu@(-∞, 2.8.4)
tensorflow@(-∞, 2.8.4)
tensorflow-gpu@[2.9.0, 2.9.3)
修复方案
将组件 tensorflow-cpu 升级至 2.10.1 及以上版本
将组件 tensorflow-gpu 升级至 2.8.4 及以上版本
将组件 tensorflow 升级至 2.10.1 及以上版本
将组件 tensorflow-cpu 升级至 2.9.3 及以上版本
将组件 tensorflow-cpu 升级至 2.8.4 及以上版本
将组件 tensorflow 升级至 2.8.4 及以上版本
将组件 tensorflow-gpu 升级至 2.10.1 及以上版本
将组件 tensorflow 升级至 2.9.3 及以上版本
将组件 tensorflow-gpu 升级至 2.9.3 及以上版本
参考链接
https://www.oscs1024.com/hd/MPS-2022-58539
https://nvd.nist.gov/vuln/detail/CVE-2022-41902
https://github.com/tensorflow/tensorflow/security/advisories/GHSA-cg88-rpvp-cjv5
https://github.com/tensorflow/tensorflow/commit/a65411a1d69edfb16b25907ffb8f73556ce36bb7
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
漏洞描述
Kodexplorer 是一个基于 Web 的文件管理器和基于 Web IDE / 浏览器的代码编辑器。
Kodexplorer 4.50 之前版本中由于 request_url_safe 函数未对用户传入的 url 参数进行有效过滤,导致未经身份验证的远程攻击者可通过恶意构造的 url 字符串(如:/)进行路径遍历攻击,进而获取 Kodexplorer 主机进程可访问的任意文件。
影响范围
kalcaddle/KodExplorer@(-∞, 4.50)
修复方案
将组件 kalcaddle/KodExplorer 升级至 4.50 及以上版本
参考链接
https://www.oscs1024.com/hd/MPS-2022-65547
https://nvd.nist.gov/vuln/detail/CVE-2022-46154
https://github.com/kalcaddle/KodExplorer/security/advisories/GHSA-6f8p-4w5q-j5j2
https://github.com/kalcaddle/KodExplorer/commit/1f7072c0ef10ee8cda82c004f04be98c
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
漏洞描述
pdfmake 是一个支持服务端/客户端 PDF 打印的开源代码库。
pdfmake 0.2.6及之前版本中由于 server.js 类中存在远程代码执行漏洞,漏洞源于用于创建 PDF 的 “/api”端点中的 eval 方法不会清理用户输入进行过滤,执行也不会在沙盒环境中进行。攻击者可利用此漏洞发送恶意的 POST 请求远程执行恶意代码。
影响范围
pdfmake@(-∞, 0.3.0-beta.1)
修复方案
升级pdfmake到 0.3.0-beta.1 或更高版本
参考链接
https://www.oscs1024.com/hd/MPS-2022-65554
https://nvd.nist.gov/vuln/detail/CVE-2022-46161
https://securitylab.github.com/advisories/GHSL-2022-068_pdfmake/
https://github.com/bpampuch/pdfmake/blob/ac6de68a0bd0931b74150b33da0dd18/dev-playground/server.js#L32
https://github.com/bpampuch/pdfmake/commit/c153a2502d1625a56b3c29324a4fddedb75aa394
情报订阅
OSCS(开源软件供应链安全社区)通过最快、最全的方式,发布开源项目最新的安全风险动态,包括开源组件安全漏洞、事件等信息。同时提供漏洞、投毒情报的免费订阅服务,社区用户可通过配置飞书、钉钉、企业微信机器人,及时获得一手情报信息推送:
https://www.oscs1024.com/cm/?src=osc
具体订阅方式详见:
https://www.oscs1024.com/docs/vuln-warning/intro/?src=osc
大家好,我是 Kagol,Vue DevUI 开源组件库和 EditorX 富文本编辑器创建者,专注于前端组件库建设和开源社区运营。
前两天检视代码时,发现PR里面有两个提交的描述信息一模一样,于是我提出应该将这两个提交合并成一个,保持提交树的清晰。
1 先储存起来!
而同事这时正在开发别的特性,工作区不是干净的,没法直接执行 git rebase 操作,于是很自然地执行
将正在修改的内容保存到一个栈中,并维持当前工作区干净。
这样就可以执行切换分支、变基等操作,这些操作能执行的前提是当前工作区是干净的。
2 使用 git rebase 合并两个提交
我们先执行 git log 命令,找到要合并的两个提交之前的那个提交:
然后执行 git rebase 变基命令:
这时会进入一个交互式命令行界面:
这时你可以移动光标,但是无法输入字符,因为这是个只读的界面,需要先输入 i 字符进入编辑态,此时界面底部会出现 标识。
下面那些以 # 开头的都是注释,只有前面两行比较关键。
每一行都由三部分组成:
- Command:需要执行的命令
- Commit ID:提交 ID
- Commit message:提交的描述信息
我们需要将 ec0218f 合并到 89f3d02 上,因此需要将第二行的 pick 改成 squash(s) 或 fixup(f),这两个命令的区别在于:
- squash(s) 是将当前的提交合并到上一行的提交上,保留两个提交的描述信息,可以在下一步中进行提交信息的编辑
- fixup(f) 也是将当前的提交合并到上一行的提交上,但不保留当前提交的描述信息
由于我们两次提交信息完全一致,没必要保留,选择 fixup(f):
修改好之后,先按 ESC 退出编辑态,然后按 :wq 保存,显示以下信息说明变基成功,两个提交已经合并在一起
执行 git log 看下效果:
可以看到两个提交已经合并在一起,并且生成了一个新的 Commit ID: 86930d03。
3 我代码没了!
1小时之后,同事慌慌张张地跟我说:
我代码没了!
我心里第一反应是:
刚才一顿变基猛如虎,不过变基变出问题来了吧?
作为一个成熟稳重的程序员,什么大风大浪没见过,于是轻轻地回了句:
少年,莫慌!你先讲下你刚才做了什么?
我没,没做什么…
没做什么代码怎么会自己丢了呢?
我就执行了一下 git stash pop,然后我之前写了一上午的代码就没…没了…
突然开始心里有点慌,把同事一上午代码搞没了,我怎么赔给人家??
但心里不能表现出来,不着急,稳住少年!
你先执行下 git stash list 看下储存栈里还有没有内容:
看到之前储存的内容还在我立马不慌了!
不再执行下 git stash pop,我看下有没有报什么错?
执行完之后果然报了一个错:
大意是:
你本地修改了文件,储存栈里的内容如果弹出会覆盖掉你本地的代码,所以导致操作失败。 然后建议你先提交你本地的修改或者将你本地的修改储存起来。 并且特意提示你你储存的内容给你保留下来了,方便你下次要用的时候可以用。
不得不说,这 Git 真是太贴心了,考虑得很周到,为 Git 点个赞👍
虽然我其实已经猜到是什么原因了,但是作为成熟稳重的程序员,我依然不动声色地问了句:git rebase 之后,git stash pop 之前,中间你是不是还改了什么东西?
哦,好像是改了 main.ts 文件,我想起来了!
你把你改的东西先撤销下,然后执行 git stash pop 试试?
4 破案!收工!
果然,执行 git stash pop 成功,之前的上百行代码都找回来了!
破案!收拾吃饭的家伙,准备收工!
哦,不行,还有两个小时才下班…
我是 Kagol,如果你喜欢我的文章,可以给我点个赞,关注我的掘金账号和公众号 ,一起交流前端技术、一起做开源!
BabyOS V8.0.0 已经发布,为 MCU 项目开发提速的代码框架
此版本更新内容包括:
1.优化驱动框架,统一驱动代码编写方法
2.增加简易状态机,助力应用程序编写
3.优化IAP功能模块,助力OTA代码编写
4.增加和优化功能模块及接口…. ….
详情查看:https://gitee.com/notrynohigh/BabyOS/releases/V8.0.0
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
Linux Mint 21.1 发布了首个 Beta 版本,为三个桌面环境提供了更新:
- Cinnamon – BETA Release
- MATE – BETA Release
- Xfce – BETA Release
下载地址:https://linuxmint.com/download_all.php
Linux Mint 21.1 不是大版本更新,主要是集成 Linux 21 发布以来的众多迭代改进,当然也增加了不少新功能,以及在视觉方面的变化。
比如新版本的主题外观有了明显的变化。Mint 团队选择了更鲜艳的颜色,同时减少了它们的使用范围,以确保不会太分散用户的注意力。本次更新还从面板移除了多个主题色,菜单和文件夹中的高亮色现在为黄色。但这次的主题颜色更新也引起了争议,因为 Mint 团队现在默认选择使用蓝色 Aqua 主题,而不是此前熟悉的薄荷绿。
下图是旧版的“薄荷绿”主题色:
对于此变化,官方的解释是:“我们不需要看起来很“绿”来体现 Linux Mint 的特点。无论如何变化,我们就是 Linux Mint,并且希望使用开箱即用看起来最令人舒服的颜色。”
Linux Mint 21.1 还有一个值得关注的变化是引入 Windows 风格的 “显示桌面” 按钮。
在这个版本中,他们采用新的 “Corner Bar” 来取代 Cinnamon 桌面面板中的 “show desktop” launcher。
Corner Bar 支持 “左键单击” 和 “中键单击”。这些操作可以被配置为显示桌面、显示 Desklets、显示工作区选择器或窗口选择器。此外还支持悬停时查看桌面。
其他变化包括:
- 改进驱动管理器
添加 “Dummy Test Device” 模式,可轻松地对各种不同的场景进行故障排除。
重新设计离线支持界面。如果处于离线状态,驱动程序管理器现在会显示一个专用界面:
如果它检测到 live USB 设备(或 DVD),则会出现不同的界面:
- ISO 验证工具
该工具用于检查和校验文件的真实性和 ISO 的完整性。
- 隐藏部分桌面图标
以下桌面图标默认会隐藏:
- Computer
- Home
- Trash
- Network
原因是这些快捷方式在用户界面中重复出现,例如:通过面板、Mint 菜单中的链接,或 Nemo 文件管理器。
点此查看更多新变化。
Inkscape 是一个免费的开源矢量图形编辑器,适用于 Linux、Windows 和 macOS。它提供了丰富的功能,广泛用于艺术和技术插图。它使用矢量图形允许以无限分辨率进行清晰的输出和渲染。Inkscape 使用标准化的 SVG 文件格式作为其主要格式。它可以导入和导出各种文件格式,包括 SVG、AI、EPS、PDF、PS 和 PNG。
Inkscape 1.2.2 是 Inkscape 最新的维护版本,该版本终于可以让使用 AppImage 的 Windows 和 Linux 用户进行 OpenClipart 导入了。
对于 macOS,拼写检查终于正常运行了、撤销/重做选项也回到了菜单中。对于 Linux,snap 包不再可以用 选项来安装,这意味着 snap 将不能访问用户主目录以外的数据。
Inkscape 1.2.2 的其他变化包括:
- 在某些情况下,当旋转物体并激活捕捉功能时,不再冻结。
- 由于性能下降,现在默认禁用 Dithering
- 对 DXF14 输出的几个修正
- TIFF 导出现在支持透明度
- JPG 和 TIFF 光栅导出时保留了 DPI 属性
- 在 Linux 中纠正了 PNG 文件的权限
- 测量工具现在可以显示形状的正确位置和尺寸
更多详情可查看:https://media.inkscape.org/media/doc/release_notes/1.2.2/Inkscape_1.2.2.html
Python 社区为 6 个不同的分支同时发布了更新,包括:Python 3.11.1, 3.10.9, 3.9.16, 3.8.16, 3.7.16 和 3.12.0 alpha 3。
这一系列的更新主要是为了修复安全问题,有些问题影响了从 Python 3.7 到 3.12 的所有版本,有些则只影响其中数个版本,部分总结如下:
- 3.7 – 3.12:gh-98739:将绑定的 libexpat 更新到 2.5.0 以修复 CVE-2022-43680 问题
- 3.7 – 3.12:gh-:不再允许在垃圾回收请求中发送的终端控制字符被打印到 stderr 服务器日志中
- 3.8 – 3.12:gh-87604:避免通过 模块发布每个解释器的活跃审计 hook 列表
- 3.7 – 3.10:gh-98517:移植 XKCP 对 SHA-3 中缓冲区溢出的修复,以修复 CVE-2022-37454 问题
- 3.7 – 3.9:gh-68966:已弃用的 mailcap 模块现在拒绝将不安全文本(文件名、MIME 类型、参数)注入到 shell 命令,此举解决了 CVE-2015-20107 问题
- ……
详情查看发布公告。
FileZilla Server 是一个免费开源的 FTP 和 FTPS 服务器,能够提供与服务器的安全加密连接。Filezilla Server 没有实现对 SFTP(SSH 文件传输协议)的支持。
FileZilla Server 1.6.0 现已发布,更新内容如下:
新的功能:
- UI:现在可以使用协议配置的安全页面中的特定选择器,直接从 UI 将 TLS 证书上传到服务器。
- UI:所有文本控件中的最大字符数已限制为合理的数字,以避免在极端情况下出现潜在的崩溃或停顿。
错误修正和小改动:
- 修复了管理协议中锁定 mutexes 的潜在问题
- MSW:如果先前安装的卸载程序已被删除,安装程序现在也可以正常工作。
- 修复了处理 TLS close_notify 警报时网络代码中的问题。
更多详情可查看:https://filezilla-project.org/
Ruby 3.2.0 RC 1 发布了,3.2.0 预览版引入基于 WASI 的 WebAssembly 支持和正则表达式超时退出机制,3.2.0 RC 1 则引入两项可显著缓解 ReDoS 攻击的改进,以及一些语言功能和性能改进。
改进的正则表达式匹配算法
从 Ruby 3.2 开始,Regexp 的匹配算法通过使用记忆技术得到了极大的改进。
改进后的匹配算法使得大多数 Regexp 匹配(实验中大约为 90%)在线性时间内完成。
对于 3.2.0 预览版本的用户:此优化可能会消耗与每个匹配的输入长度成比例的内存。预计不会出现实际问题,因为此内存分配通常会延迟,并且正常的 Regexp 匹配最多应消耗 10 倍的内存输入长度。
该功能最初的提议是 https://bugs.ruby-lang.org/issues/19104
其他值得注意的新功能
语法建议
- (以前的 )的功能已集成到 Ruby 中,可以帮助找到错误的位置,例如丢失或多余的 end 。
[Feature #18159]
错误高亮
- 现在它指向 TypeError 和 ArgumentError 的相关参数
语言
- 匿名 rest 和关键字 rest 参数可以作为参数传递,而不仅仅是在方法参数中使用。
[Feature #18351]
更多性能改进和细节变化可在发布公告中查阅。
回顾一下 3.2.0 预览版中引入的功能:
基于 WASI 的 WebAssembly 支持
这是基于 WASI 的 WebAssembly 支持的初始移植。此项特性使得 CRuby 二进制文件可在 Web 浏览器、Serverless Edge 环境和其他 WebAssembly/WASI 嵌入器上使用。目前,此移植可在不使用 Thread API 的前提下通过基本和引导测试套件的测试。
正则表达式超时退出机制
此版本引入了正则表达式超时退出机制。
由于正则表达式匹配会耗费不少时间,当代码试图向不受信任的输入匹配低效的正则表达式时,攻击者可能会利用它进行 DoS 攻击(即正则表达式 DoS,或称作 ReDoS)。
根据 Ruby 应用程序的要求进行配置,可以防止或显着降低 DoS 的风险。请注意, 是全局配置项,如果希望对某些特殊的正则表达式使用不同的超时设置,需要使用 关键字 。
此项特性的最初提案:https://bugs.ruby-lang.org/issues/17837
Blender 是一个免费和开源的 3D 计算机图形软件工具集,用于创建动画电影、视觉效果、艺术、3D 打印模型、交互式 3D 应用、VR 和计算机游戏。Blender 3.4 现已正式发布,该版本包括 Cycles 中的路径引导、新的雕刻和 paint masking 工具、几何节点视口叠加、新的 UV 编辑工具、改进的性能等等。
具体一些更新亮点包括:
- 除了 Linux 上现有的 X11 支持之外,现在还启用了 Wayland 支持。
- 通过使用英特尔的 Open Path Guiding 库集成了路径引导支持,以提高采样质量。Open path Guiding 库目前仅适用于基于 CPU 的渲染。
- 现在支持带有 HIP 的 AMD Radeon RX 7000 系列 (RDNA3) 显卡。
- 修复了在 Linux 上使用 ROCm 5.3 及更新版本时 Vega 和 RDNA1 显卡的 texture issues。
- FreeType 字体缓存以使用更少的资源和更好的性能。
- WebP 图像缩略图生成更快,同时使用更少的 RAM。
- Blender 的视频渲染现在支持 FFmpeg AV1 编解码。
- 现在在 Linux 下支持 Eevee headless 渲染。
- UV 编辑器中添加了一个新的基于几何体的 relax brush。
- 几何节点有一个新的评估系统。
- 支持 MTL 文件中的 PBR 扩展。
- Blender 内部网格格式的内部数据结构发生了很大的变化。
更多详情可查看 3.4 release notes。
下载地址:http://ftp.vim.org/graphics/blender/release/Blender3.4/
VS Code 1.74 已发布,此版本主要带来如下优化:
- 自定义资源管理器自动显示– 决定哪些文件在资源管理器中滚动到视图中。
- 隐藏活动栏和面板徽章– 通过切换状态徽章,简化编辑器 UI。
- 笔记本和差异视图的音频提示– 单格运行结果、添加或删除行的声音。
- 合并编辑器撤消/重做– 快速恢复或重新应用合并冲突操作。
- 管理不安全的存储库– 防止对不属于您的文件夹进行 Git 操作。
- JavaScript console.profile 集合– 轻松创建 CPU 配置文件,并在 VS Code 中查看。
- Go to Definition from return – 跳转到 JavaScript/TypeScript 函数的顶部。
- 远程隧道– 创建到任何设备的连接,无需 SSH。
- Jupyter Notebook“Just My Code”调试– 避免进入 Python 库代码。
- 开发容器 GPU 支持– 创建开发容器时请求 GPU。
下面对部分功能作介绍:
自定义资源管理器的自动显示逻辑
此版本引入新设置 explorer.autoRevealExclude ,如果启用了自动显示(explorer.autoReveal,默认为 true),此设置允许您配置哪些文件在资源管理器中自动显示。
autoRevealExclude 设置使用 glob 模式来排除文件,类似于 files.exclude,也支持通过 when 子句进行兄弟匹配。
默认值不包括 node 和 bower 模块:
设置编辑器指示器、悬停和链接可用键盘导航
设置编辑器中的指示器、悬停和链接现在可以通过键盘导航,一些链接的样式也进行了调整,以便在设置编辑器中保持更好的一致性。在制表位和保持键盘焦点方面,设置编辑器指示器悬停表现得更好。
这种改进仍处于试验阶段,目前仅对设置编辑器指示器悬停启用,而不是对 VS 代码中的所有悬停启用。
隐藏视图容器的徽章
与通过右键单击视图容器隐藏视图容器的方式类似,现在也可以隐藏容器上的徽章(显示在活动栏、面板和侧栏中)。
徽章通常显示特定视图容器的数字、图标或进度指示器,例如,源代码管理视图的待处理更改数。
管理不安全的 Git 仓库
VS Code 使用 git.exe 执行所有 Git 操作。 从 Git 2.35.2 开始,用户无法在非当前用户拥有的文件夹的存储库中运行 Git 操作,因为该存储库被认为具有潜在的不安全性。
从此版本开始,如果尝试打开此类可能不安全的存储库,VS Code 将在源代码管理视图中显示欢迎视图以及错误通知。 欢迎视图和通知都带有“管理不安全存储库”命令,该命令允许您查看可能不安全的存储库列表,手动将它们标记为安全仓库,然后再打开它们。
管理不安全存储库命令也可在命令面板中使用, 将存储库标记为安全会将存储库位置添加到 safe.directory git 配置。
终端快速修复改进
终端快速修复现在显示在代码操作控件中,以与编辑器中的体验保持一致。
远程隧道
Remote Tunnels 现在可作为 VS Code 稳定版的预览功能使用,远程隧道允许您从任何设备、任何地方安全地访问您的机器与 VS 代码。
要启用远程隧道访问,可以:
- 从帐户菜单或命令面板中选择打开远程隧道访问。
- 从安装了 VS Code 并位于 PATH 上的计算机运行 。
- 下载新的 VS Code CLI ,并运行.
打开隧道访问后,您可以使用 vscode.dev 从任何设备连接到计算机,或使用VS Code 桌面中的 Remote – Tunnels扩展。
要了解更多信息,请查看该功能的博客文章或远程隧道文档。
JavaScript 调试
支持 console.profile
JavaScript 调试器现在支持 console.profile。在调试器下运行时,该功能将为 console.profile() 和 console.profileEnd() 之间的代码收集 CPU 配置文件。
生成的 .cpuprofile 文件将保存在您的工作区文件夹中,可以使用 VS Code 的内置配置文件查看器打开和查看。
支持嵌套源映射
有时,尤其是在 monorepo 设置中,源代码可能会被编译一次,然后重新编译或再次捆绑。在许多情况下,这个问题会导致生成的包的源映射引用了第一步中创建的编译文件。
JavaScript 调试器现在自动递归地解析源映射,无需额外步骤即可调试原始源文件。
TypeScript 4.9
VS Code 现在附带 TypeScript 4.9,带来了新的 TypeScript 语言功能,例如运算符和自动访问器。在工具方面则对文件监视进行了改进,并进行了许多其他修复和改进。
查看 TypeScript 4.9 公告,了解有关此更新的更多信息。
Go to Definition on return
JavaScript 和 TypeScript 现在支持在 return 关键字上运行 Go to Definition 以快速跳转到返回函数的顶部,在处理长的、复杂的或高度嵌套的函数时很有用。
可以使用 Go to Definition 命令/键绑定 (F12) 或简单地使用 Cmd/Alt + 单击 return 关键字。
远程开发扩展
远程开发扩展允许使用容器、远程计算机或适用于 Linux 的 Windows 子系统(WSL) 作为功能齐全的开发环境。此版本的亮点包括:
- 开发容器 GPU 支持
- 开发容器 Cygwin / Git Bash 套接字转发
- 远程隧道扩展 – 无需 SSH 即可连接到远程计算机。
可以在远程开发的发行说明中了解新的扩展功能和错误修复。
更多功能可以在发布公告中细阅。
Microsoft PowerToys 是 Windows 系统实用程序,供高级用户调整和简化其 Windows 体验,可最大限度地提高生产力。
以下是 PowerToys v0.65 版本中的一些重要更新内容:
亮点
- 代码库已经升级兼容 .NET 7
- Quick Accent 现在可以显示所选字符的描述
- ColorPicker 现在支持添加自定义格式
- 将依赖项 ModernWPF 降级到 0.9.4,以避免某些虚拟化技术的问题
已知问题
- Text Extractor(文本提取器)工具在某些情况下无法识别运行 Windows 10 的 ARM64 设备上的文本
- 安装 PowerToys 后,PowerRename 和 Image Resizer 的新的 Windows 11 上下文菜单项在系统重启前可能不会出现
- 有报告称,用户无法打开 “设置” 窗口。这是由一些应用程序的不兼容造成的(RTSS RivaTuner统计服务器就是一个已知的例子)
快速启动器
目前一个新的 PR 显示,微软将为 PowerToys 引入快速启动器,用户可以通过系统托盘中的图标来启动各种 PowerToys 模块。
特点:
- 显示可通过启动器启动的激活模块
- 每个模块都有工具提示,以显示激活的快捷键
- 可以打开设置和文档
- 被禁用的模块将不被显示
更多详情可查看:https://github.com/microsoft/PowerToys/releases/tag/v0.65.0
本次升级内容:
build
- spring-boot > 2.7.6
- nacos.version > 2.1.2
- spring-boot-admin.version>2.7.7
- jasypt.version>3.0.4
- aliyun-java-sdk-core.version>4.6.2
- esdk-obs-java.version>3.22.3.1
- qiniu-java-sdk.version>7.12.0
- gson.version>2.8.9
- jsoup.version>1.15.3
- JustAuth.version>1.16.5
- okhttp3.version>4.10.0
- mybatis.version>3.5.10
- mybatis-spring.version>2.0.7
- jasypt.version>3.0.4
- lombok.version>1.18.24
- tencentcloud-sdk-java.version>3.1.548
- aliyun-java-sdk-core.version>4.6.2
- aliyun-dysmsapi.version>2.0.22
- bce-java-sdk.version>0.10.217
- ip2region.version>2.6.5
refactor
- lamp-sms: 腾讯和阿里短信发送适配新版本api
- lamp-authority: 登录日志获取浏览器、操作系统等信息方式变更
- lamp-util: spring.factories 文件替换为 org.springframework.boot.autoconfigure.AutoConfiguration.imports
- lamp-log-starter: 适配 ip2region.version 2.6.5
- lamp-cloud-starter: 优化 OkHttpClient 配置
- lamp-echo-starter: 启动时扫描指定包名下需要回显的实体类,优化echo首次回显慢的问题
- lamp-echo-starter: 回显集合数据时,转换为普通类型进行查询
fix
- 解决 @Async 使用时, ThreadLocal会有问题
关于lamp
(简称灯, 英文名:lamp),她是一个项目集,为满足高内聚低耦合设计原则,将一个大项目拆解为以下几个子项目:
-
lamp-util:后端工具集
-
lamp-cloud:基于Spring Cloud实现的后台
-
lamp-boot:基于Spring Boot实现的后台
-
lamp-job:基于xxl-job集成本项目的分布式定时任务
-
lamp-generator:代码生成器
-
lamp-web:前端
lamp-cloud 简介
是基于 + + + 开发的微服务中后台快速开发平台,专注于多租户(SaaS架构)解决方案,亦可作为普通项目(非SaaS架构)的基础开发框架使用,目前已实现插拔式 数据库隔离、SCHEMA隔离、字段隔离 等租户隔离方案。
她拥有自研RBAC(基于租户应用的角色权限控制体系)、网关统一鉴权、数据权限、优雅缓存解决方案、防缓存击穿、前后端统一表单校验、字典数据自动回显、可视化前后端代码生成器、支持多种文件存储、支持多种短信邮件发送接口、灰度发布、防XSS攻击、防SQL注入、分布式事务、分布式定时任务等功能; 支持多业务系统并行开发, 支持多服务并行开发,是中后台系统开发脚手架的最佳选择。
lamp-cloud 代码简洁,注释齐全,架构清晰,非常适合个人学习以及中小企业作为基础框架使用。采用Spring Cloud Alibaba、SpringBoot、Mybatis、Seata、Sentinel、RabbitMQ、FastDFS/MinIO、SkyWalking等主要框架和中间件。 本项目旨在实现基础框架能力,不涉及具体业务。
关注项目
- 官网:https://tangyh.top
- 源码:github
- 源码:gitee
一、背景介绍
随着4G网络的推广和网络带宽的提升,视频成为互联网用户主要的消费载体,用户通过短视频来分享和浏览信息。由此视频的编辑功能越来越重要、越来越普遍。视频编辑的App也如雨后春笋般涌现。 为更好地推动得物App社区业务的发展,得物也自研符合得物需求的视频编辑工具。我们致力于打造一个“更快、更强”的视频编辑工具。
二、视频编辑工具介绍
为了让大家更好地了解得物App的视频编辑工具,我们先简单介绍一下视频编辑工具的主要功能。
下面是得物App视频编辑工具的主要功能:
视频编辑工具的重点如下:
-
视频编辑工具需要操作的资源:
- 文字:包括普通的文字、特殊的艺术字、花字等等;
- 图片:包括静态图,如JPEG/PNG等等,也包括HEIC/GIF等动态图;
- 视频:包括各种各样的视频(各种编码和封装格式),主流的格式一般是MP4的封装格式、H264视频编码格式、AAC音频编码格式等等;
- 音频:包括各种各样的音频(各种编码和封装格式),当然视频当然也是包含音频轨道的。
-
视频编辑工具主要的操作方式:
- 操作图片、视频帧:我们知道视频是一帧一帧的图片组成的,所以操作视频帧和操作图片是一样的道理,我们通过添加一些特效在图片和视频帧上面,实现一些有趣的效果来吸引用户。
- 操作音频:主流的操作音频方式如倍速、调整音量、变调等等,都是现今短视频的主要玩法。
-
视频编辑工具最终生成的是一个新的视频,这个视频将特定的资源应用一些特效生成一个新的视频。
下面的流程图可以很方便地让大家了解视频编辑的工作流程。为了方便,我们输入一个视频,加上一些特效,生成一个新的视频。
从上面的流程可以看出来,原始视频A.mp4经过解封装分离出音频轨道和视频轨道,对它们解码之后,对音频数据应用音频特效、对视频帧数据应用视频特效,然后编码封装合成一个新的视频。当然解码和编码都是有一个队列控制的,流程图上标注了,没有深入展开,大家了解即可。
经过上面的介绍,大家对视频编辑工具有了大概得了解,其实衡量一个视频编辑工具做得好不好,主要从下面这几个方面着手:
-
内存占用情况
-
导出视频的速度如何
-
导出视频的清晰度如何
下面从这三方面详细展开给大家阐述得物App的视频编辑工具优化的心路历程。
三、内存优化
性能是所有程序好不好的首要指标,一个工具即使功能再强大,但是一点就崩溃,或者用着用着内存暴涨、应用卡死,估计这个应用不能称为一个优秀的应用,下面我们具体谈一谈视频编辑工具的优化检测方案。
优化内存从良好的编码习惯开始,尤其对音视频这种对内存需求非常高的应用而言。例如一个1080 * 1920的视频,解码出来原始数据一帧图片大小也是1080 * 1920,占用内存是1080 * 1920 * (8 * 3 ) / 8 = 5.93 MB,一个视频帧就占用这么大,1秒一般有30帧,那得占用177.9MB,如果不加控制,那不管多高性能的手机也经不住这样的折腾。希望下面的内存检测和优化方案可以给你带来一些帮助。
3.1 合理设计队列
上面我们在介绍视频编辑流程的视频谈到了解码队列和编码队列的概念。其实队列这个概念在音视频中使用非常频繁,正是因为内存的限制,所以才引入队列这个控制方式。大家可能还有点懵,但是看完下面的流程图,我相信你一定会豁然开朗。
我们仅选取解码的部分来分析一下队列的重要应用。
在视频编辑工具中有几个重要的队列:
-
解码过程中:
- Video Packet Queue:视频解码之前Packet存放的队列,一般建议的队列大小是100
- Audio Packet Queue:音频解码之前Packet存放的队列,一般建议的队列大小是150
- Video Frame Queue:视频解码之后Frame存放的队列,一般建议的队列大小是3
- Audio Frame Queue:音频解码之后Frame存放的队列,一般建议的队列大小是8
-
编码过程中:
- Encode Video Packet Queue:视频编码之后Packet存放的队列,一般建议的大小是100
- Encode Audio Packet Queue:音频编码之后的Packet存放的队列,一般建议的大小是150
按照上面的方式设计队列的大小,可以在保证功能正常的情况下最大程度的降低内存占用,提升用户体验。
3.2 排查内存泄漏
Android上排查内存泄漏的方式有很多,这里介绍两种:
-
Asan检测
-
Profile检测
Asan全称是AddressSanitizer是一种基于编译器的快速检测的工具,用于检测原生代码中的内存错误问题,Asan可以解决如下四种核心问题:
-
堆栈和堆缓冲区上溢、下溢
-
释放之后堆重新使用问题
-
超过范围的堆栈使用情况
-
重复释放、错误释放问题
Asan的使用方式建议参考google官方文档,这儿就不多作介绍了: https://github.com/google/sanitizers/wiki/AddressSanitizer
关于Profile的使用,如果需要检测Native内存使用情况,需要满足API>=29,大家在使用的时候需要非常注意。
下面是我们在demo中应用Asan抓取的堆栈:
显示message是:heap-use-after-free on address 0x004ac1e41080 说明是使用了已经释放掉的内存了,再继续看,这个内存具体在什么地方被释放的?0x004ac1e41080 is located 0 bytes inside of 1792-byte region [0x004ac1e41080,0x004ac1e41780) Asan一个很大的优势就是可以追踪内存释放的路径,防止出现内存泄漏和野指针问题,特别是野指针,一旦出现特别难排查,简直是C++开发的噩梦,希望大家用好工具,同时培养良好的C++编码习惯。
3.3 优化线程
另一个影响内存的重要因素是线程,视频编辑工具涉及到的线程非常多,线程的使用得遵循一些基本的原则:
-
尽量少创建线程
-
尽量少使用pthread_mutex_t
-
本着功能隔绝原则使用线程
-
能同步就别异步
以编辑模块为例,这儿列一下我们使用到的所有线程:
-
GL处理线程
-
视频解封装线程
-
视频中视频轨道解码线程
-
视频音频轨道解码线程
-
抽取缩略图线程
-
音频编码线程
-
视频编码线程
-
视频封装线程
如果插入了独立的音频文件,还需要添加两个额外的线程:
-
音乐文件播放线程
-
音乐文件解码线程
上面列出的是一个视频编辑工具能正常工作所必备的最少线程,如果你的视频编辑工具中多了什么线程,我们建议可以适当优化一下,毕竟少一个线程,可以少一分开销,而且少一分线程同步的工作。
我们在底层也按照Android的消息机制重写了一套C++层的消息分发SDK,这个我们后续会另外分享文章阐释我们定制的消息分发SDK,这儿点到为止。
四、提升导出视频的速度
我们使用视频编辑工具,最终是希望导出一个视频,如果这个导出的过程很慢,那肯定是无法忍受的,从上面的介绍我们已知视频的导出需要经过“解码——应用特效——编码”的过程,其中解码和编码这两个过程对速度的影响至关重要。因为解码和编码视频需要耗费大量的资源,目前主要有两种方式——“软解/编码”和“硬解/编码”。
如果你使用过FFmpeg或者其他使用CPU进行视频编解码的来处理视频的话,你可能已经遇到了处理速度慢的问题。这主要是因为软编码和软解码使用CPU进行运算,而CPU在处理视频上的速度远低于DSP芯片;简而言之“软解/编码”主要通过CPU来工作,通过CPU来主导大量的计算工作,是原始的处理方式,当然耗费的时间也比较长;“硬解/编码”是通过GPU来处理,GPU是专用的图形处理芯片,对视频的解码和编码有专门的优化,所以编码和解码的速度非常快。
Android上使用MediaCodec来实现“硬解/编码”,iOS上使用VideoToolBox来实现“硬解/编码”,这里着重介绍Android上编码解码的速度优化。
从上面的流程我们可以看出,编码在解码的后面,一个时长60s(30fps)的视频,需要解码1800帧,然后编码1800帧视频才能完整生成另外一个视频,这样串行的等待是耗时的主要原因。
这时候我们参考多线程方案,将一个60s的视频均分为两段,然后这两段视频同时进行解码操作,生成导出了两个30s的临时缓存视频文件,随后将这两个30s的视频合并为一个60s的B.mp4视频,最后删除临时缓存文件,这样我们只需要同时处理900帧的数据,理论上可以提升一倍的导出速度。
这就是并行导出,下面是得物App并行导出的基本流程。
首先我们要明确导出视频是需要消耗资源的,这个资源就是MediaCodec,最终是送入到GPU中处理,一个手机中的MediaCodec实例是有限的,正常情况下,一个手机可以提供的MediaCodec实例最多有16个,如果当前使用的MediaCodec实例超过16个,那么手机将无法正常工作。MediaCodec资源是手机中的所有App共同持有。所以并行分段的个数不是越多越好。
-
只有一段,需要两个MediaCodec(一个用来解码视频,一个用来编码视频),注意:音频的解码和编码可以不要用MediaCodec,毕竟音频的耗时少多了,不是瓶颈。
-
分成两段需要四个MediaCodec,分成三段需要六个MediaCodec,分成四段需要八个MediaCodec,以此类推。
下面是并行导出的测试结果:
两段并行速度提升50% ~ 70%,内存增加20%, 三段并行速度提升60% ~ 90%,内存增加80%;并行超过三段的话就无法明显提升速度了。我们比较建议并行两段,在一些性能很好的机型上并行三段。
如果有些同学对视频导出过程中文件操作还有疑问的,下面的示意图可以比较清楚地看出并行导出操作本地文件的过程:
-
并行导出的过程中,生成了两个临时文件
-
并行导出完成后,这两个临时文件合并为一个新的文件,两个临时生成的文件被删除了(节省用户宝贵的存储空间)
-
原始文件jeffmony_out.mp4并没有被删除/修改
Tips:目前我们在处理过程中生成的临时文件和最终的适配文件都会保存在/sdcard/Pictures/duapp/Compile/下,而在处理完成后的临时文件清理过程会触发在某些机型上的保护机制,建议后续调整到App的私有目录下。
当然还有其他的提升导出速度的建议,例如在视频帧特效处理的过程中,我们建议:
-
尽量采用FBO/EBO/ABO方式处理texture
-
纹理如果过大要进行压缩
-
严禁采用glFinish()
这些做法都是我们在视频编辑开发过程中的切实经验,希望能给大家带来一些帮助。
五、提升导出视频的清晰度
一个视频编辑功能是否足够优秀,其中的一个重要指标就是同等条件下导出的视频是否足够清楚,通常而言,衡量视频是否清晰的有两种方式:
-
主观标准:找一些用户观看不同的视频,根据用户的观感输出视频清晰度的对比结果,用户一般根据色彩、画面亮度、柔和度等来评估清晰度。
-
客观标准:利用算法计算视频画面质量分,目前比较推荐Netflix推出的开源库VMAF来计算视频帧的质量分。
实际上主观标准是比较准确的,但是可操作性比较差,特别是处理海量视频的时候,需要大量的人力,无法有效开展,因此日常工作中还是推荐客观标准进行海量计算,主观标准进行重点判断。具体的可以结合业务的重要程度来开展。
下面结合我们实际的工作给出具体提升视频清晰度的方式:
-
视频基础编码信息优化
- Profile优化:Profile有三种Level,分别是Baseline、Main、High,其中Baseline Profile对应清晰度最低,Android 3.0之后的版本都支持的,Main Profile清晰度比Baseline Profile清晰度要好,但是从Android 7.0之后才支持,High Profile清晰度最高,也是从Android 7.0之后才支持。我们在设置Encoder Profile Level之前,需要判断一下当前是否支持。
- Bitrate码率设置: 视频码率是视频数据传输时单位时间内传送的数据位数。单位是kbps,望文生义,码率越大,单位时间填充的数据就越多,视频质量就越高。但码率也不是设置的越大越好,超过必要限度,对视频画质的提升已不明显,建议采用合适的factor来调整码率。Bitrate = width * height * frameRate * factor,其中factor=0.15。
- Bitrate Mode: 有三种通过的编码模式——VBR(可变码率)、CBR(固定码率)、ABR(平均码率),其中ABR是最好的方式,可以兼顾质量和视频大小。
- B帧设置: 视频有I帧、P帧、B帧构成,其中I帧最大,P帧次之,B帧最小,我们在编码时尽量多设置B帧(在合理的范围内),并不会降低清晰度,但是可以大大降低视频的大小,这样我们就可以相应地调大码率,最终实现了提升清晰度的目标。
-
HEVC编码优化: 使用HEVC编码,可以保证在不增加文件大小的情况下,大大提升视频的清晰度。在相同的图像质量下,HEVC编码的视频比H.264编码的视频约减少40%
-
色彩调优
- 综合调整亮度、对比度、色温、饱和度、锐度等颜色参数,进而优化整体的视频画面,让视频画面看上去“更清晰”。
-
超分算法 : 采用ESRGAN算法,利用机器学习的优势对图片和视频进行去模糊、Resize、降噪、锐化等处理,重建图片,实现对图片的超分辨率处理。
- 特征提取:计算噪点
- 非线性映射:放大,模糊化噪点
- 图像重建:差分,平滑过度,去噪
-
下面是使用超分算法处理前后的对比图,可以很明显地看出右边的图更加清晰,少了很多噪点、图片更亮、过度更平滑。
如果大家想了解视频清晰度优化的技术细节,可以参考文章–视频清晰度优化指南
六、总结
本文开篇从介绍得物App的主要功能展开,提出了视频编辑工具优化的三个维度:
-
优化内存占用
-
提升视频导出速度
-
提升导出视频的清晰度
其中在“提升视频导出速度”时重点谈到了“并行导出”的技术方案,从最终的结果来看,视频导出速度的提升非常明显,同时也非常清楚地解释了“并行导出”过程中为什么生成临时文件?为什么有必要在导出完成之后删除临时文件?尽力给用户带来较好的体验。
最后在“提升导出视频的清晰度”中重点提到的超分算法应用效果提升明显,超分之后的视频帧相比原帧图更加清晰、噪点更少,而且细节部分更加真实。
后续我们还会结合AR特效输出更多有意义的技术分享,敬请期待。
*文 /Jeff Mony
关注得物技术,每周一三五晚18:30更新技术干货
要是觉得文章对你有帮助的话,欢迎评论转发点赞~
Djot(发音:/dʒɑt/)是轻量的标记语法, 包含许多派生自 CommonMark 的功能,同时修复了一些使 CommonMark 语法复杂且难以有效解析的问题。
Djot 属于 Markdown 的升级版,且 Djot 的功能比 CommonMark 更全面,支持定义列表、脚注、表格、几种新的内联格式(插入、删除、高亮、上标、下标)、数学、智能标点符号、可应用于任何的属性素,以及用于块级 (block-level)、内联级 (inline-level) 和原始内容 (raw content) 的通用容器。
在 Djot 的语法中,对硬换行的解析与常见的 Markdown 不同。
比如使用 Markdown 可以写成这样:
但在 Djot 中,如果使用了块级素,一定要采用硬换行:
对于列表也是同样的处理:
- Markdown
- Djot
Djot 的解释器采用解释性语言 Lua 编写,据称速度很快,可以生成 AST、渲染 HTML,以及语法高亮显示或 linting 工具。
微软近日公布了实施 Manifest V3 和逐步淘汰 Manifest V2 浏览器扩展的更新路线图,更新后企业可以继续在配置了相应策略的系统上使用 Manifest V2 扩展,时间至少会到 2024 年 1 月。根据博客文章,微软可能会进一步延长对 Manifest V2 扩展的支持,但目前还没有最终的定论。
Manifest V3 在浏览器开发商、扩展开发者、企业组织和普通用户中被积极讨论,虽然大部分人都在批评 Manifest V3,但各大浏览器厂商仍然在陆续推进 Manifest V3 的支持工作,只不过各个厂商的支持程度各不相同。比如 Firefox 就计划在支持 Manifest V3 的同时支持 Manifest V2 功能,Vivaldi 没有具体说明如何实现,仅仅表示内容拦截扩展可以继续正常使用。
微软已于 2022 年 7 月停止接受 Manifest V2 的新扩展,但并没有在 Microsoft Edge 中取消支持,Manifest V2 和 V3 扩展均可以安装在最新版本的 Microsoft Edge 中,开发者也仍然可以为现有的扩展推送更新,以维护或增加新的功能。
微软 Edge Manifest V2 支持的官方迁移时间表还没有根据新信息进行更新。迁移过程目前还是处于上述这样的第一阶段。
到了下一阶段,微软将不再允许开发者更新 Manifest V2 的扩展,扩展开发者只能发布升级到 Manifest V3 的扩展。也是从这个阶段开始时,Edge 用户不能再运行 Manifest V2 扩展,除非企业策略被配置为允许 Manifest V2 扩展。
在第三阶段,也是最后一个阶段,无论企业策略如何设置,Manifest V2 的扩展都将无法在任何版本的 Edge 中发挥作用。
12 月 4 日,自由软件基金会 (FSF) 和 GNU 项目创始人 RMS 以线上形式在 EmacsConf 2022 大会发表了演讲,主题是《What I’d like to see in Emacs》。
RMS 说道,GNU Emacs 是他发布的第一个 GNU 程序,在这个过程中,他了解到软件许可证以及捍卫软件自由的知识。
于是 RMS 在演讲开头首先强调了 GNU 操作系统的目标。他表示 GNU 不仅仅是要在技术层面和使用层面做得好,它的主要目标——甚至可以说是整体目标,就是为了让大众自由使用软件,并帮助他们珍视和捍卫这份自由。
在谈到 GNU Emacs 支持的编程语言时,RMS 认为 Emacs 最不应该支持的语言是 JavaScript。但他说这不是因为语言本身存在问题。
RMS 表示自己不懂 JavaScript,他听说别人评价它相当笨拙,且设计得不好,但他不了解这些。他也不是因为这些问题而发表上面的观点。
RMS 认为 JavaScript 的糟糕之处并非语言本身,而是人们使用它的方式。大多数情况下,Web 服务器会将 JavaScript 编写的程序不知不觉地发送到用户的机器上。如此一来,这个无法知晓作者的程序就会在用户的电脑上运行,并做着用户不知道的事。这些举动无疑违背了 RMS 一直倡导和追求的“自由”。他认为让 Emacs 不支持 JavaScript 属于捍卫自由的一种方式。
当然,RMS 知道这个问题并非 JavaScript 导致,“罪魁祸首”是现代浏览器厂商。他提到了刚诞生时的互联网,当时的网页负责描述内容,浏览器则负责渲染内容,用户拥有自由控制浏览器的权限。但从大约二十年前开始, 随着商业公司希望对用户屏幕上显示的内容进行越来越多的控制 ,浏览器的复杂性呈爆炸式增长。他们发明了很多功能来控制它,用户无法真正自定义某些内容的显示方式。因为整个问题的关键是商业公司控制了浏览器,以及在 Web 中运行的应用。这些都和 JavaScript 密切相关。
RMS 在本次大会上除了谈论“自由”哲学,更多的内容还是关于 Emacs 本身,他期望 Emacs 能带来更丰富的功能,比如集成 LibreOffice 和 TeX 中的优点。以及简化 Emacs 的命令界面,优化维护方式等。
RMS 完整演讲内容
- 文字:https://emacsconf.org/2022/talks/rms/
- 视频:https://media.emacsconf.org/2022/emacsconf-2022-rms–what-id-like-to-see-in-emacs–main.webm
延伸阅读
- RMS 谈论自由软件运动现状:整体处境恶化、苹果打造 “监狱”
历时两年,Asahi Linux 宣布推出第一个公开的 Apple Silicon GPU 驱动程序版本。目前尚处在 alpha 阶段,“但它已经足够好,可以运行流畅的桌面体验和一些游戏”。
根据介绍,此版本为所有当前的 Apple M 系列系统提供 work-in-progress OpenGL 2.1 和 OpenGL ES 2.0 支持;其足以满足 GNOME 和 KDE 等桌面环境的硬件加速,以及较老的 3D 游戏 (如 Quake3 和 Neverball) 等的运行,可以在 4K 条件下以每秒 60 帧的速度运行上述所有的游戏。但值得注意的是,这些驱动程序尚未通过 OpenGL (ES) 一致性测试,所以可能会存在一些 bug。
开发团队表示,他们下一步的计划是支持更多应用。虽然 OpenGL (ES) 2 对某些应用来说已经足够了,但新的应用(尤其是游戏)需要更多的 OpenGL 功能。OpenGL (ES) 3 带来了大量的新功能,如 multiple render targets、multisampling 和 transform feedback。关于这些功能的工作正在进行中,但它们都需要大量的额外开发工作,而且都需要在 OpenGL (ES) 3.0 问世之前完成。
此外,Vulkan 相关的工作也在计划当中。虽然现在只提供 OpenGL,但开发团队在设计时已经考虑到了 Vulkan;其为 OpenGL 所做的大部分工作都将重新用于 Vulkan。不过按照估计,开发团队将优先推出 OpenGL 2 驱动而不是 Vulkan 1.0 驱动。原因在于 OpenGL 使用范围更广,因此优先支持 OpenGL 更有意义。
Asahi Linux 开发团队的工作内容包括有:
- 用于映射内存和提交内存映射工作的内核驱动程序
- 一个用户空间驱动程序,用于将 OpenGL 和 Vulkan 调用转换为图形内存中的硬件特定数据结构
- 将 GLSL 等着色编程语言翻译成硬件指令集的编译器
团队成员间进行了分工合作:由 Alyssa Rosenzweig 编写 OpenGL 驱动和编译器、Asahi Lina 编写内核驱动程序并帮助开发 OpenGL、Dougall Johnson 与 Alyssa 一起进行指令集的逆向工程,以及 Ella Stanforth 研究 Vulkan 驱动程序,重用内核驱动、编译器和一些与 OpenGL 驱动共享的代码。
“当然,仅凭我们自己是不可能在两年内构建一个 OpenGL 驱动的。感谢自由和开源软件的力量,我们站在了 FOSS 巨头的肩膀上”。
编译器实现了一个“NIR”后端、内核驱动程序使用了 Linux 内核的“直接渲染管理器 (DRM)”子系统来以最小化 boilerplate;OpenGL 驱动程序在 Mesa 内部实现了“Gallium3D”API,“通过 Mesa 和 Gallium3D,我们受益于 30 年的 OpenGL 驱动程序开发,以及将 OpenGL 转换为更简单的 Gallium3D 的通用代码。感谢 NIR、Mesa 和 Gallium3D 令人难以置信的工程设计,我们的逆向工程师团队可以专注于剩下的东西:Apple 硬件”。
由于驱动程序尚处于开发中,因此仍存在许多已知问题,官方提供了一份如何报告 bug 的快速指南。用户可定期更新软件包以获得更新和错误修复,更多详情可查看公告。
文章目录
- 一、背景
- 二、环境准备
- 三、具体实施步骤
-
- 3.1、安装ansible
- 3.2、配置主机清单
- 3.3、测试主机连通性
- 3.4、创建相关目录
- 3.5、下载openGauss软件包到files目录
- 3.6、创建变量文件
- 3.7、创建安装时需要的xml模板
- 3.8、创建任务文件
- 四、执行自动化安装
-
- 4.1、校验语法
- 4.2、自动化安装openGauss
- 4.3、安装完成后验证
一、背景
由于IT建设的快速发展,当数据中心业务突增,需要快速部署多套的数据库时,给运维工作带来了不小的压力和挑战,作为运维人员该如何面对面对这种困境呢?另外由于个人的习惯等也会导致所部署的环境不一定与规划完全一致,那么对以后的运维也会产生一定的负面影响。很显然,这种传统的方式已经无法适应当前的情景了,自动化运维应运而生,ansible在自动化运维和devops 的应用中崭露头角。
本文基于ansible工具实现 openGauss 的一键批量部署,传统的部署方式是先修改系统配置、安装依赖包、创建omm用户和组、配置环境变量、上传安装包以及解压、安装等步骤。
按照这个流程和思路,我们把这些操作弄成剧本编排(playbook),交给ansible来做。
二、环境准备
2台主机:
一台为Ansible的管理主机(10.10.10.142),操作系统为CentOS Linux release 7.9.2009 (Core);
另外一台为需要部署openGauss的主机(10.10.10.150),操作系统为CentOS Linux release 7.9.2009 (Core)。
三、具体实施步骤
3.1、安装ansible
–在10.10.10.142上进行安装Ansible
yum install epel-release -y
yum install ansible –y
–配置/etc/ansible/ansible.cfg
3.2、配置主机清单
修改主机清单/etc/ansible/hosts,添加主机列表
10.10.10.150为本次需要安装openGauss的主机
3.3、测试主机连通性
3.4、创建相关目录
[root@cs79-mysql:~]# cd /etc/ansible/roles/
[root@cs79-mysql:/etc/ansible/roles]# mkdir -p openGauss_Install/{files,vars,tasks,templates}
[root@cs79-mysql:/etc/ansible/roles]# tree openGauss_Install/
openGauss_Install/
├── files
├── tasks
├── templates
└── vars
4 directories, 0 files
上述目录主要作用如下:
files:存放需要同步到异地服务器的安装文件或者配置文件;
tasks:openGauss安装过程需要进行的执行的任务;
templates:用于执行openGauss安装的模板文件,一般为脚本;
vars:安装openGauss定义的变量;
3.5、下载openGauss软件包到files目录
安装包下载地址:https://opengauss.org/zh/download.html
[root@cs79-mysql:/etc/ansible/roles]# cd openGauss_Install/files/
[root@cs79-mysql:/etc/ansible/roles/openGauss_Install/files]# # wget https://opengauss.obs.cn-south-1.myhuaweicloud.com/3.1.0/x86/openGauss-3.1.0-CentOS-64bit-all.tar.gz
–2022-10-09 21:42:01– https://opengauss.obs.cn-south-1.myhuaweicloud.com/3.1.0/x86/openGauss-3.1.0-CentOS-64bit-all.tar.gz
Resolving opengauss.obs.cn-south-1.myhuaweicloud.com (opengauss.obs.cn-south-1.myhuaweicloud.com)… 121.37.63.38, 139.159.208.64, 139.159.208.243
Connecting to opengauss.obs.cn-south-1.myhuaweicloud.com (opengauss.obs.cn-south-1.myhuaweicloud.com)|121.37.63.38|:443… connected.
HTTP request sent, awaiting response… 200 OK
Length: (117M) [application/gzip]
Saving to: ‘openGauss-3.1.0-CentOS-64bit-all.tar.gz’
100%[==================================================================================================================================================================================================>] 123,022,609 38.4MB/s in 3.2s
2022-10-09 21:42:04 (37.1 MB/s) – ‘openGauss-3.1.0-CentOS-64bit-all.tar.gz’ saved [/]
3.6、创建变量文件
[root@cs79-mysql:~]# vi /etc/ansible/roles/openGauss_Install/vars/main.yml
#安装包名称
openGauss_software: openGauss-3.1.0-CentOS-64bit-all.tar.gz
#解压目录
install_dir: /opt/software/openGauss
#omm用户密码
omm_password: openGauss@123
#数据库密码
db_password: openGauss@123
3.7、创建安装时需要的xml模板
[root@cs79-mysql:~]# vi /etc/ansible/roles/openGauss_Install/templates/cluster_config.j2
3.8、创建任务文件
3.9、创建剧本调用文件
[root@cs79-mysql:~]# vi /etc/ansible/playbook/InstallopenGauss.yml
- name: Install openGauss
hosts: openGaussdb
remote_user: root
roles:- openGauss_Install
四、执行自动化安装
4.1、校验语法
校验语法通过后,执行下一步安装
4.2、自动化安装openGauss
4.3、安装完成后验证
至此,整个自动化部署openGauss完毕,如果有多台机器需要部署,添加主机相关信息到/etc/ansible/hosts,再执行ansible-playbook即可。
作者:鸿惊九天
openGauss: 一款高性能、高安全、高可靠的企业级开源关系型数据库。
🍒如果您觉得博主的文章还不错或者有帮助的话,请关注一下博主,如果三连点赞评论收藏就更好啦!谢谢各位大佬给予的支持!
一次利用 ChatGPT 给出数据抓取代码,借助 NebulaGraph 图数据库与图算法预测体坛赛事的尝试。
作者:古思为
蹭 ChatGPT 热度
最近因为世界杯正在进行,我受到这篇 Cambridge Intelligence 的文章启发(在这篇文章中,作者仅仅利用有限的信息量和条件,借助图算法的方法做出了合理的冠军预测),想到可以试着用图数据库 NebulaGraph 玩玩冠军预测,还能顺道科普一波图库技术和图算法。
本来想着几个小时撸出来一个方案,但很快被数据集的收集工作劝退了,我是实在懒得去「FIFA 2022 的维基」抓取所需的数据,索性就搁浅、放了几天。
同时,另一个热潮是上周五 OpenAI 发布了 ChatGPT 服务,它可以实现各种语言编码。ChatGPT 可实现的复杂任务设计包括:
- 随时帮你实现一段指定需求的代码
- 模拟任意一个 prompt 界面:Shell、Python、Virtual Machine、甚至你创造的语言
- 带入给定的人设,和你聊天
- 写诗歌、rap、散文
- 找出一段代码的 bug
- 解释一段复杂的正则表达式的含义
ChatGPT 的上下文联想力和理解力到了前所未有的程度,以至于所有接触它的人都在讨论新的工作方式:如何掌握让机器帮助我们完成特定任务。
所以,当我试过让 ChatGPT 帮我写复杂的图数据库查询语句、解释复杂图查询语句的含义、解释一大段 Bison 代码含义之后,我突然意识到:为什么不让 ChatGPT 帮我写好抓取数据的代码呢?
抓取世界杯数据
我真试了下 ChatGPT,结果是:完全可以,而且似乎真的很容易。
整个实现过程,基本上我像是一个代码考试的面试官,或是一个产品经理,提出我的需求,ChatGPT 给出具体的代码实现。我再试着运行代码,找到代码中不合理的地方,指出来并给出建议,ChatGPT 真的能理解我指出的点,并给出相应的修正,像是:
这一全过程我就不在这里列出来了,不过我把生成的代码和整个讨论的过程都分享在这里,感兴趣的同学可以去看看。
最终生成的数据是一个 CSV 文件:
- 代码生成的文件 world_cup_squads.csv
- 手动修改、分开了生日和年龄的列 world_cup_squads_v0.csv
上面的数据集包含的信息有:球队、小组、编号、位置、球员名字、生日、年龄、参加国际比赛场次、进球数、服役俱乐部。
这是手动删除了 CSV 表头的数据集 world_cup_squads_no_headers.csv。
图方法预测 2022 世界杯
图建模
本文用到了图数据库 NebulaGraph 和可视化图探索工具 NebulaGraph Explorer,你可以在阿里云免费申请半个月的试用,入口链接是👉🏻 申请使用云端 NebulaGraph。
图建模(Graph Modeling)是把真实世界信息以”点–>边“的图形式去抽象与表示。
这里,我们把在公共领域获得的信息映射成如下的点与边:
点:
- player(球员)
- team(球队)
- group(小组)
- club(俱乐部)
边:
- groupedin(球队属于哪一小组)
- belongto(队员属于国家队)
- serve(队员在俱乐部服役)
而队员的年龄、参加国际场次(caps)、进球数(goals)则很自然作为 player 这一类点的属性。
下图是这个 schema 在 NebulaGraph Studio/Explorer(后边称 Studio/Explorer) 中的截图:
我们右上角的保存后,便能创建一个新的图空间,将这个图建模应用到图空间里。
这里可以参考下 Explore 草图的文档:https://docs.nebula-graph.com.cn/3.3.0/nebula-explorer/db-management/draft/
导入数据进 NebulaGraph
有了图建模,我们可以把之前的 CSV 文件(无表头版本)上传到 Studio 或者 Explorer 里,通过点、选关联不同的列到点边中的 vid 和属性:
完成关联之后,导入,就能把整个图导入到 NebulaGraph。成功之后,我们还得到了整个 的关联配置文件:nebula_importer_config_fifa.yml,你可以直接拖拽整个配置,不用自己去配置它了。
这里可以参考 Explorer 数据导入的文档:https://docs.nebula-graph.com.cn/3.3.0/nebula-explorer/db-management/11.import-data/
数据导入后,我们可以在 schema 界面查看数据统计。可以看到,有 831 名球员参加了 2022 卡塔尔世界杯,他们服役在 295 个不同的俱乐部:
这里我们用到了 Explorer 的 schema 创建的文档:https://docs.nebula-graph.com.cn/3.3.0/nebula-explorer/db-management/10.create-schema/#_6
探索数据
查询数据
下面,我们试着把所有的数据展示出来看看。
首先,借助 NebulaGraph Explorer,我用拖拽的方式画出了任意类型的点(TAG)和任意类型点(TAG)之间的边。这里,我们知道所有的点都包含在至少一个边里,所以不会漏掉任何孤立的点。
让 Explorer 它帮我生成查询的语句。这里,它默认返回 100 条数据(),我们手动改大一些,将 LIMIT 后面的参数改到 10000,并让它在 Console 里执行。
初步观察数据
结果渲染出来是这样子,可以看到结果自然而然地变成一簇簇的模式。
这些外围、形成的簇多是由不怎么知名的足球俱乐部,和不怎么厉害的国家队的球员组成,因为通常这些俱乐部只有一两个球员参加世界杯,而且他们还集中在一个国家队、地区,所以没有和很多其他球员、国家队产生连接。
图算法辅助分析
在我了 Explorer 中的两个按钮之后(详细参考后边的文档链接),在浏览器里,我们可以看到整个图已经变成:
这里可以参考 Explorer 的图算法文档:https://docs.nebula-graph.com.cn/3.3.0/nebula-explorer/graph-explorer/graph-algorithm/
其实,Explorer 这里利用到了两个图算法来分析这里的洞察:
- 利用点的出入度,改变它们的显示大小突出重要程度
- 利用 Louvain 算法区分点的社区分割
可以看到红色的大点是鼎鼎大名的巴塞罗那,而它的球员们也被红色标记了。
预测冠军算法
为了能充分利用图的魔法(与图上的隐含条件、信息),我的思路是选择一种利用连接进行节点重要程度分析的图算法,找出拥有更高重要性的点,对它们进行全局迭代、排序,从而获得前几名的国家队排名。
这些方法其实就体现了厉害的球员同时拥有更大的社区、连接度。同时,为了增加强队之间的区分度,我准备把出场率、进球数的信息也考虑进来。
最终,我的算法是:
- 取出所有的 的关系,过滤其中进球数过少、单场进球过少的球员(以平衡部分弱队的老球员带来的过大影响)
- 从过滤后的球员中向外探索,获得国家队
- 在以上的子图上运行 Betweenness Centrality 算法,计算节点重要度评分
算法过程
首先,我们取出所有进球数超过 10,场均进球超过 0.2 的 的子图:
为了方便,我把进球数和出场数也作为了 serve 边上的属性了。
然后,我们全选图上的所有点,左边的工具栏,选择出方向的 边,向外进行图拓展(遍历),同时选择将拓展得到的新点标记为旗帜的 icon:
现在,我们获得了最终的子图,我们利用工具栏里的浏览器内的图算法功能,执行 BNC(Betweenness Centrality)
最后,这个子图变成了这样子:
预测结果
最终,我们根据 Betweenness Centrality 的值排序,可以得到最终的获胜球队应该是:巴西 🇧🇷!
其次是比利时、德国、英格兰、法国、阿根廷,让我们等两个礼拜回来看看预测结果是否准确吧 :D。
注:排序数据(其中还有非参赛球队的点)
Betweenness Centrality
Brazil🇧🇷 3499
Paris Saint-Germain 3073.00
Neymar 3000
Tottenham Hotspur 2740
Belgium🇧🇪 2587.0
Richarlison 2541
Kevin De Bruyne 2184
Manchester City 2125
İlkay Gündoğan 2064
Germany🇩🇪 2046
Harry Kane (captain 1869
England🏴 1864
France🇫🇷 1858.00
Argentina🇦🇷 1834.00
Bayern Munich 1567
Kylian Mbappé 1535.00
Lionel Messi (captain 1535.00
Gabriel Jesus 1344
原文地址:https://discuss.nebula-graph.com.cn/t/topic/11584
谢谢你读完本文 (///▽///)
如果你想尝鲜图数据库 NebulaGraph,记得去 GitHub 下载、使用、(^з^)-☆ star 它 -> GitHub;和其他的 NebulaGraph 用户一起交流图数据库技术和应用技能,留下「你的名片」一起玩耍呀~
Jay 是一位经验丰富并且对质量要求很高的开发者,对 Angular、React 等多种框架都很熟悉,我们在开源社区认识,在我做开源社区运营的过程中,Jay 给了我很多帮助,他也是 React DevUI 开源组件库的创建者。
2021年11月,由 Jay 主导发起了 React DevUI 开源组件库项目,经过一年多的孵化🐣,终于在发布 18.0.0 正式版本🎉
特性:
- 基于最新的++技术栈
- 包含个灵活、高质量的组件
- 包含配套的 Admin 系统(持续完善中)
- 支持主题定制
- 支持国际化
- 支持 TypeScript
- 支持 Monorepo
- 支持单测试(持续完善中)
- 包含完善的设计指南 / 开发规范 / 贡献流程
- 完善的构建 / 发布 / 测试 / 依赖管理等基础设施
除了使用了最新的技术进行组件开发之外,React DevUI 还对组件的细节体验进行极致的打磨,比如:
- 🌈 所有组件和网站均遵循WCAG 2.0规范做了无障碍设计(Accessibility),比较明显的就是焦点管理和对键盘方向键的支持,欢迎到我们的官网体验。
- ⚡ 针对大数据量的列表做了极致的虚拟滚动,渲染和筛选数十万数据无任何卡顿,感兴趣可以体验下我们的Select组件。
- ✨ 在API设计上,我们也经过了仔细的推敲和思考,所有组件的 API 都以易用和是否符合预期为设计原则,简洁、灵活、开发者友好,从Compose组件就可以窥见一斑。
为什么要开发这个组件库
接触前端从 Vue2 开始,深入学习的是 Angular(公司项目),这里插一句,Angular 作为前端开发者真的可以好好学一下,主要是学习其编程思想和比较与其它框架的差异。我个人对于 React 还是非常感兴趣的,所以当时就看了 React17 官网文档和相关教程,state => ui 这种纯粹的驱动模式简直是完美,我喜欢这种可靠的渲染,但奇葩的是异步函数里调用 setState 会立即重新渲染,虽然到目前为止我都没有过多时间了解 React18 之前的东西,不过当时我就想这绝对是个 bug 收集器。
可能缘分是个奇妙的东西,我不知道怎么就看到的 React18 的新特性,这个 concurrency(并发)那可真是看的我人麻了,这绝对会是目前最好的框架,那一刻 jay 知道必须写个组件库。
组件库的技术选型
开发组件库的技术栈为 react18 + ts + sass,react18 + ts 没啥好说的,这里说说为什么用 sass。
当初也有人建议用 css in js,其实在这之前我是不知道这个概念的,毕竟没用过 React,了解之后发现其灵活性的确是 sass 无法比拟的,但是我真的要为了这种灵活性舍弃:
- 开发成本,sass 作为最受欢迎的 css 扩展,但凡前端几乎了解,不了解的也无所谓,sass 完全兼容 css 语法。
- 样式独立,样式独立于组件,我希望开发其它框架组件时不用再写一套样式,本质是一种模块化,即样式的模块化,我相信好处不止于此。
- 性能。
最终我选择 sass,而且 sass + css 变量 的灵活性不见得不如 css in js,特别是有样式规范的情况下。
组件遵循的规范
组件库从诞生之初就遵循下面最基本的规范:
- 如果有 无障碍 支持,那么一定要实现。
- 国际化(i18n)支持。
- SSR 支持。
- 移动设备支持。
后面开发中添加了组件类支持:
- Compose 组合
- Form 表单
其它的一些规范:
- Prop 命名,如支持 form 的输入为 ,弹窗状态统一为 。
- 列表类组件的大数据支持,实现时间复杂度为 O(n),如 Select 选择框。
- 一些边边角角我实在记不起来了。
样式规范
组件样式规范:
- 命名遵循 BEM 规范。
- 明显的聚焦或激活样式反馈。
- 内敛的动画,即动画变化属性数量尽可能少(一般小于等于 2 个),如 Button 聚焦时仅变化背景色或边框。
优势在于是由经验丰富的技术大佬主导的开源项目
说吧,为啥用你这组件库。
所有组件由 jay 开发,这意味着:
- 所有组件均遵循规范。
- 统一的 API 设计。
- 统一的样式设计。
- 性能的把控。
- 极简的大小,npm 包 未压缩 不超过 1MB!
网址
- GitHub – 欢迎大家点亮Star🌟
- React DevUI 官网
- React DevUI Admin 官网
— END —
我是 Kagol,如果你喜欢我的文章,可以给我点个赞,关注我的掘金账号和公众号 ,一起交流前端技术、一起做开源!
最近,我被一款叫做 ChatGPT 的人工智能(AI)聊天机器人,刷屏了。网上有人说它是搜索引擎杀手,还有人说它将取代程序员…
最后,我还是没扛住铺天盖地的赞美,跑去注册了个账号,抱着调侃“人工智障”的心态,想要调戏 ChatGPT 一番。于是就有了下面的对话:
此时,我内心毫无波澜。
此刻,我放下了傲慢与偏见。
对不起,是我鲁莽了,我才是智障。
不得不承认 ChatGPT 确实有点东西,然后我就问了一嘴它有没有开源。
ChatGPT 没有给出准确的答复,所以我去查了下截止到本文发布时 ChatGPT 并没有开源,而且官方也没有任何关于 ChatGPT 的开源计划。
那 ChatGPT 未来会不会开源呢?为了回答这个问题,我去查了它背后的公司、创始人、提供的服务、开源的项目,综合这些信息文章最后我给出了自己的看法:不会。如果你也对这个话题感兴趣的话,那不妨一起来看看吧。
特别说明:ChatGPT 官方并未给出明确的开源计划,以下均为我的个人观点,仅供参考。
谁做出了火爆全网的 ChatGPT?
ChatGPT 是由 OpenAI 公司开放的免费 AI 聊天机器人服务。
OpenAI 是一个人工智能研究实验室,由营利组织 OpenAI LP 与母公司非营利组织 OpenAI Inc 组成,目的是促进和发展友好的人工智能,让更多人受益。它成立于 2015 年底,总部位于旧金山,目标是通过与其他机构和研究者的“自由合作”,向公众开放专利和研究成果。
程序员应该对 OpenAI 这个公司并不陌生,因为知名的人工智能编程助手 Copilot 就是它和 GitHub 合作开发的。
如果你不是程序员,那这个人你应该听说过。OpenAI 有两位创始人其中一位是埃隆·马斯克,对!就是那个特斯拉汽车的 CEO,最近刚收购了 Twitter 的那位。他曾在 2014 年,开放了特斯拉汽车的所有专利。另一位创始人是原 Y Combinator(美国著名创业孵化器)总裁山姆·阿尔特曼,美国斯坦福大学计算机系辍学生。
OpenAI 资金这块,创始人一个当过首富一个是创投,肯定是不缺投资,况且在 2019 年的时候微软还给它投了 10 个亿美。
如果将创始人比作公司的 DNA,那 OpenAI 无论是公司目标还是 DNA,对待“开放”都是积极的态度。虽然 OpenAI 不缺钱,但既然是公司就肯定要赚钱,所以也不会什么都“白给”。
OpenAI 与开源
OpenAI 喊着开放的口号,到底有没有做过“开放”的事儿?
我在 GitHub 上找到了 OpenAI 开源组织的地址:
https://github.com/openai
接下来,就通过介绍 4 款 OpenAI 开源的知名开源项目,从它们身上看看 OpenAI 对待开源的态度。
1.强化学习训练场:Gym
Star 数:29.2k|编程语言:Python(99.9%)
这是一个用于强化学习研究的 Python 工具包,包含了许多经典的强化学习环境,如游戏、机器人控制、计算机视觉等。它还提供了一个统一的接口,可以让用户定义任务、训练智能体和评估性能。简单来说就是 Gym 提供问题和环境,你用 AI 框架来解。就像刷算法的网站提供算法题和测试用例,让你十分方便地刷算法一样。
比如,下面就是 Gym 提供的一个场景:
一个推车上立着一根棍子,让智能体(AI)控制推车左右移动,保证车子上的棍子不倒。
地址:https://github.com/openai/gym
2.强大的语言识别系统:Whisper
Star 数:17.6k|编程语言:Python
该项目是一款开源的自动语音识别系统,支持包括中文在内的多种语言。尤其是在快语速、口音、背景噪音等场景,依旧表现出色能够达到极高的准确率。
地址:https://github.com/openai/whisper
3.用文字生成图片:DALL·E
Star 数:9.3k|编程语言:Python
它能够将文本描述映射到对应的图像,并生成对应的图像。例如,如果向 DALL·E 提供文本描述“午后晒太阳的小猫”,它就会生成一张图片,展示一只猫在晒太阳。需要注意的是 DALL·E 并未完全开源,下图是用最新的 DALL·E 2 生成,该项目没有开源仅提供生成图片的服务。
地址:https://github.com/openai/DALL-E
4.大型语言模型:GPT
GPT 是 Generative Pretrained Transformer 的缩写,一种由 OpenAI 提出的大型预训练语言模型。它使用了许多深度学习技术,可以生成文本内容,也可以进行文本分类、问答等任务。GPT 与传统的机器学习方法不同,它通过预先训练来学习大量文本数据,然后可以进行各种自然语言处理任务。它的训练方法非常有效,在许多 NLP 挑战赛中取得了优异的成绩。
GPT-2 和 GPT-3 是两种不同的大型语言模型,GPT-3 是 GPT-2 的一个升级版,它在功能和性能方面都有所提高,比如具有更大的模型规模、更高的准确率、更快的训练速度和处理更复杂任务的能力,但GPT-3 并未开源。
ChatGPT 就是基于 GPT-3.5 最新训练出来的模型。
GPT-2:https://github.com/openai/gpt-2
GPT-3:https://github.com/openai/gpt-3
通过这些开源项目,我们不难看出 OpenAI 确实是以开放的态度,分享技术、开放研究成果,而且几乎每一次开源新项目都会掀起一波热潮。
但近些年,OpenAI 为了保证核心竞争力和提高盈利能力,开始选择部分开源或者不开源,逐步过渡到通过提供 API 有偿地提供服务。
最后
我想看到这里,关于「ChatGPT 未来会开源吗?」的问题,想必大家心中已经有了答案。
我个人的观点是:ChatGPT 不会开源。因为 GPT-3 截止目前都没有开源,所以我感觉 ChatGPT(3.5)开源的希望就更渺茫了,而且 OpenAI 商业化的趋势也已经显而易见。对此你怎么看,欢迎留言发表看法。
最后,虽然 ChatGPT 并不完美但已经让我重新审视 AI 的能力,甚至已经开始畅想那种:用类似与人对话的方式操作计算机,一种全新的人机交互方式。但我深知此事任重而道远,减少期望才会看到更多惊喜,慢慢来吧。
有人用 ChatGPT 写代码、解 bug、找乐子…还有人熬夜蹭它的热度,就为了一个“赞”。没错,正是在下。如果您觉得这篇文章写得还不错,就请给我点一个赞,您的支持就是我更新的动力。我们下期见~
基于文本识别(OCR)技术的成熟与应用,日常生活中的大部分“印刷体识别”需求都能被满足,替代了人工信息录入与检测等操作,大大降低输入成本。
而对于复杂的手写体识别需求,业界识别质量却参差不齐。大部分手写体存在字迹潦草,排版不固定,背景复杂,且不同的字体风格各异等问题,给手写体识别带来极大的挑战,不过华为HMS Core机器学习服务的OCR文字识别技术可以帮助解决识别问题。
华为HMS Core 机器学习服务基于OCR识别技术推出最新手写体识别能力,使用拍照设备将纸质信息转化为图片,对图片中横排的手写中文、英文、阿拉伯数字等符号进行检测和识别,支持印刷体识别、手写体识别、行间混排等,可以精准返回手写体和印刷体的类别。同时,对字迹潦草、连笔等情况和试卷、书信等场景进行专项优化,识别准确率可达95%以上。
效果演示:
应用场景:
由于手写体字迹的随意性很大,如背景繁杂、字体大小不一、角度倾斜等,这些问题都有可能直接影响到字符的识别准确率。
基于此,HMS Core 机器学习服务通过海量样本集训练来提升其鲁棒性,不管是浅色背景、田字格、米字格、四方格,还是在有下划线的情况下,识别准确率均可达95%以上,同时支持45°倾斜字体的识别。
手写体识别具有很强的实用性,可广泛应用于试卷批改、笔记电子化、大规模的数据统计如人口普查、信息登记等场景中。
1.智能批改
使用手写体识别技术,对学生日常作业、考试试卷中的手写内容进行自动识别,实现学生作业、考卷的线上批改,大幅提升教师的工作效率和质量。
2.笔记电子化
针对纸质手写文档、手写笔记等内容,同时支持墨水屏识别,实现对手写文字内容的扫描及存储。
开发者只需集成手写体识别服务,就可以将手写纸质文档、笔记、发票等图片中的文字转换成文本格式,供文字处理软件进一步编辑加工。有了它,即使是潦草、模糊的手写信息也能够识别,可以有效解决人工录入速度慢、易出错的问题,从而大大节约时间成本,提高录入效率。
总之,不管是印刷体,还是手写体,HMS Core机器学习服务都能准确识别,开发者们可以根据自己的业务需求自主选择。
了解更多详情>>
访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解 HMS Core 最新技术资讯~
Nginx rewrite 详解
本篇主要介绍 nginx 的 rewrite 重定向这个功能进行 详解介绍, 以及介绍它的使用场景
1. rewrite 基本介绍
rewrite是实现URL重写的关键指令,根据regex (正则表达式)部分内容,重定向到replacement,结尾是flag标记。
基本语法:
- regex: 正则表达式语句进行规则匹配
- replacement: 将正则匹配的内容替换成replacement
- flag: last | break | redirect | permanent
- last : 本条规则匹配完成后,继续向下匹配新的location URI规则
- break: 本条规则匹配完成即终止,不再匹配后面的任何规则
- redirect : 回302临时重定向,浏览器地址会显示跳转后的URL地址 (防爬虫)
- permanent : 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
rewrite 使用位置
- server : 在server中针对所有的请求
- location : 在 location 中则针对 单个匹配路径的
- If
2. server 中使用 rewrite
直接在server中使用 rewrite ,
2.1 rewrite 外部站点
rewrite 到外部站点 是指 replacement 部分 是一个完整的 带 http/https 的 外部路径 ,它的特点是 浏览器会再次请求这个新的站点 所以浏览器上的地址一定会发生变化 不受 flag 参数影响
下面的配置是 所有的请求都转发了 https://www.askajohnny.com
经过测试可以发现 直接跳转过去 并且 浏览器中的地址也直接变成了 https://www.askajohnny.com , 待会我们再详细讨论 什么时候会变化这个地址
, 因为我的登录当时填写的回调是 http,又因为互联的审核太麻烦 太慢 所以干脆就这样配置
2.2 rewrite 到内部站
点
rewrite 到内部站点是指 replacement 不带http/https 而是内部的另外一个路径 , 相当于访问隐藏起来的这个 内部路径,
经过测试 当访问 www.testfront.com/222.html 的时候
- flag = last 浏览器不会变化 隐藏了 后端 /my.gif 地址
- flag = break 浏览器不会变化 隐藏了 后端 /my.gif 地址
- flag = redirect 和 permanent 浏览器变化了URL 变更状态码 302和 301
3. location 中使用rewrite
location 中也可以使用 rewrite 意思是只有匹配到 这个location 后才经过 rewrite 的正则通过后 再跳转
希望是如果 访问的后缀 是 数字.html 则 返回 my.gif 图 ,其他的都代理到 http://www.testbackend.com
经过测试 只有访问www.testfront.com/数字.html 的时候 才能获取到 my.gif 文件
4. 使用场景模拟
4.1 基于域名跳转
比如现在你所在的公司 网站域名是 www.testfront.com 现在需要使用新的域名 www.newtestfront.com 替代, 但是旧的域名不能作废, 需要让旧的域名跳转到新的域名上 , 并且保持后面参数不变
4.2 基于客户端 IP 访问跳转
今天公司业务新版本上线,要求所有 IP 访问任何内容都显示一个固定维护页面,只有公司IP:192.168.200.100访问正常。
此时如果是 172.16.225.1 访问就可以到 后端, 如果是其他的客户端ip 访问就只能到 weihu.html 页面
总结
本篇主要介绍了 nginx 中 rewrite 的基本概念 以及基本的使用方式 ,rewrite 可以出现在 server , location , if 中
并且介绍了 什么时候才会变化浏览器URL , 以及介绍了2个模拟场景
-
rewirte 内部站点
当rewrite 到内部站点的时候 会根据 flag 参数 last break不变 redirect permanent 变化
-
rewrite 外部站点 带http/https 等
当rewrite 外部站点 不管flag 参数 浏览器URL都会进行变化 相当于浏览器进行了 二次请求了
欢迎大家访问 个人博客 Johnny小屋
欢迎关注个人公众号
应用发布后,尤其在发布初期,我们要格外关注应用的性能稳定性,如ANR、画面卡顿、加载慢等问题,如果不能及时被监测及解决,将会给用户带来非常糟糕的体验,导致低评、差评,甚至造成部分意向用户直接流失。HUAWEI AppGallery Connect性能管理服务,除了提供分钟级的应用性能监控能力,整体帮您快速定位、精准修复性能问题外,还提供了单点查询及日志回捞功能,可用于分析并解决特定用户遇到的问题,和获取指定用户终端上的日志进行分析,帮您更快速、更精准地定位、解决重点用户的问题,进一步提升应用的用户体验。
单点查询即查看单用户应用性能数据,页面目前覆盖了“ANR分析”、“页面分析”、“慢启动追踪”与“网络分析”子项。
您可以通过在“用户标识”搜索框输入应用中设定的用户标识,查询某个用户的应用性能监控数据。
基本步骤:进入“应用性能管理”页面,选择“单点查询”页签即可使用。
ANR,即Application Not Responding,也就是应用程序无响应。如果Android应用的界面线程处于阻塞状态的时间过长,就会触发“应用无响应”(ANR) 的错误。单点查询菜单下的ANR分析可以展示单用户在选定时间范围内应用ANR事件的发生次数、应用启动次数、用户ANR率,以及问题列表。
“问题列表”中右侧“操作”列的“查看详情”,可查看具体问题的“ANR问题详情”页面。该页面展示了ANR问题发生时的详细信息,包括设备信息、系统信息、应用信息以及主线程堆栈、其他线程堆栈、系统日志、ANR信息,帮助您快速定位解决ANR问题。另外还提供了记录导出功能,您可以可将该页面所有数据导出,进行对比分析。
页面分析展示单用户在选定时间范围内所打开的屏幕名称总览,某个屏幕的慢加载与慢呈现占比等信息。
屏幕名称右侧“操作”列的“查看详情”,可查看该屏幕详情页面,包括屏幕加载及屏幕呈现的具体信息。屏幕加载主要分析用户切换屏幕是否流畅,统计当前屏幕打开到用户可交互的时间。屏幕呈现主要分析该屏幕内容是否呈现完整,统计当前屏幕打开到内容呈现完毕的时间。详细的屏幕指标说明请参见查看体验分析数据。
慢启动追踪展示单用户冷启动与热启动时慢启动的发生事件列表,每条事件记录冷/热启动的发生时间、耗时、应用版本、系统版本以及接入方式等信息。
网络分析展示单用户在选定时间范围内访问的URL以及相应的网络指标信息。
查看单点查询功能更多详情。
什么是日志回捞?
为方便您根据详细的客户端运行日志进行问题定位分析,我们提供了自定义日志功能,最大2MB。所记录的日志内容记录在本地,当您需要查看此日志内容时,可以在AGC控制台创建日志回捞任务,获取指定用户终端上的日志进行查看分析。
1、选择“日志回捞”页签,“创建任务”开始创建。
(注:创建日志回捞任务之前需先接入应用,设置用户标识等,以此决定哪些用户可以接收到回捞任务。具体步骤及代码指导请见文档)
在创建任务界面,填写任务名称、任务描述、拉取日志的时间范围,以及用户标识。
相关参数及说明:
任务名称
String类型,限长100个字符,仅支持中文、字母、下划线和数字。
任务描述
String类型,限长255个字符,仅支持中文、字母、下划线和数字。
拉取时间范围
格式为yyyy-MM-dd HH:mm:ss – yyyy-MM-dd HH:mm:ss,最长时间跨度为7天。
用户标识
最多支持20个用户,以逗号分割。
注意
需要与应用中调用SDK接口APMS.getInstance().setUserIdentifier(String userIdentifier)时传入的参数值一致。
2、配置完成后“确定”,您创建的回捞任务将展示在任务列表中。您可以在任务列表该任务右侧“操作”列的“查看详情”,查看详细的日志信息。
3、详情页面分为“任务信息”和“日志信息”两个区域展示。
任务信息:展示任务的名称、进度、拉取时间范围等概要信息。
日志信息:展示获取到的自定义日志的具体信息。
- 如果拉取到多个用户日志,可以通过右侧“用户标识”下拉框来切换用户,以查看不同用户的日志信息。
- 具体的日志信息,可以在线查看,也可以“下载日志文件”下载以“用户标识+日志文件名”命名的日志文件到本地查看。
- 支持通过“时间”、“级别”和“关键字”对日志进行过滤搜索。
查看日志回捞功能更多详情。
单点查询、日志回捞功能目前已经支持Android应用使用场景,其他应用场景敬请期待。
立即使用>>>性能管理服务
如您有其他建议或疑问,可通过 agconnect@huawei.com邮箱进行咨询,感谢您对HUAWEI AppGallery Connect的支持!
作者:谢泽华
背景
众所周知单个机房在出现不可抗拒的问题(如断电、断网等因素)时,会导致无法正常提供服务,会对业务造成潜在的损失。所以在协同办公领域,一种可以基于同城或异地多活机制的高可用设计,在保障数据一致性的同时,能够最大程度降低由于机房的仅单点可用所导致的潜在高可用问题,最大程度上保障业务的用户体验,降低单点问题对业务造成的潜在损失显得尤为重要。
同城双活,对于生产的高可用保障,重大的意义和价值是不可言喻的。表面上同城双活只是简单的部署了一套生产环境而已,但是在架构上,这个改变的影响是巨大的,无状态应用的高可用管理、请求流量的管理、版本发布的管理、网络架构的管理等,其提升的架构复杂度巨大。
结合真实的协同办公产品:京办(为北京市政府提供协同办公服务的综合性平台)生产环境面对的复杂的政务网络以及京办同城双活架构演进的案例,给大家介绍下京办持续改进、分阶段演进过程中的一些思考和实践经验的总结。本文仅针对ES集群在跨机房同步过程中的方案和经验进行介绍和总结。
架构
部署Logstash在金山云机房上,Logstash启动多个实例(按不同的类型分类,提高同步效率),并且和金山云机房的ES集群在相同的VPC
Logstash需要配置大网访问权限,保证Logstash和ES原集群和目标集群互通。
数据迁移可以全量迁移和增量迁移,首次迁移都是全量迁移后续的增加数据选择增量迁移。
增量迁移需要改造增加识别的增量数据的标识,具体方法后续进行介绍。
原理
Logstash工作原理
Logstash分为三个部分input 、filter、ouput:
input处理接收数据,数据可以来源ES,日志文件,kafka等通道.
filter对数据进行过滤,清洗。
ouput输出数据到目标设备,可以输出到ES,kafka,文件等。
增量同步原理
1. 对于T时刻的数据,先使用Logstash将T以前的所有数据迁移到有孚机房京东云ES,假设用时∆T
2. 对于T到T+∆T的增量数据,再次使用logstash将数据导入到有孚机房京东云的ES集群
3. 重复上述步骤2,直到∆T足够小,此时将业务切换到华为云,最后完成新增数据的迁移
适用范围:ES的数据中带有时间戳或者其他能够区分新旧数据的标签
流程
准备工作
创建ECS和安装JDK忽略,自行安装即可
下载对应版本的Logstash,尽量选择与Elasticsearch版本一致,或接近的版本安装即可
https://www.elastic.co/cn/downloads/logstash
1) 源码下载直接解压安装包,开箱即用
2)修改对内存使用,logstash默认的堆内存是1G,根据ECS集群选择合适的内存,可以加快集群数据的迁移效率。
3. 迁移索引
Logstash会帮助用户自动创建索引,但是自动创建的索引和用户本身的索引会有些许差异,导致最终数据的搜索格式不一致,一般索引需要手动创建,保证索引的数据完全一致。
以下提供创建索引的python脚本,用户可以使用该脚本创建需要的索引。
create_mapping.py文件是同步索引的python脚本,config.yaml是集群地址配置文件。
注:使用该脚本需要安装相关依赖
拷贝以下代码保存为 create_mapping.py:
配置文件保存为config.yaml:
以上代码和配置文件准备完成,直接执行 python create_mapping.py 即可完成索引同步。
索引同步完成可以取目标集群的kibana上查看或者执行curl查看索引迁移情况:
全量迁移
Logstash配置位于config目录下。
用户可以参考配置修改Logstash配置文件,为了保证迁移数据的准确性,一般建议建立多组Logstash,分批次迁移数据,每个Logstash迁移部分数据。
配置集群间迁移配置参考:
增量迁移
预处理:
1. @timestamp 在elasticsearch2.0.0beta版本后弃用
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/mapping-timestamp-field.html
2. 本次对于京办从金山云机房迁移到京东有孚机房,所涉及到的业务领域多,各个业务线中所代表新增记录的时间戳字段不统一,所涉及到的兼容工作量大,于是考虑通过elasticsearch中预处理功能pipeline进行预处理添加统一增量标记字段:gmt_created_at,以减少迁移工作的复杂度(各自业务线可自行评估是否需要此步骤)。
3. 检查pipeline是否生效
4. 各个index设置对应settings增加pipeline为默认预处理
5. 检查新增settings是否生效
增量迁移脚本
schedule-migrate.conf
index:可以使用通配符的方式
query: 增量同步的DSL,统一gmt_create_at为增量同步的特殊标记
schedule: 每分钟同步一把,”* * * * *”
问题:
mapping中存在join父子类型的字段,直接迁移报400异常
解决方法:
https://discuss.elastic.co/t/an-routing-missing-exception-is-obtained-when-reindex-sets-the-routing-value/
https://github.com/elastic/elasticsearch/issues/26183
结合业务特征,通过在filter中加入小量的ruby代码,将_routing的值取出来,放回logstah event中,由此问题得以解决。
示例:
作者:王嘉宁、汪诚愚、邱明辉、石秋慧、王洪彬、黄俊、高明
近日,阿里云机器学习平台 PAI 与华东师范大学高明教授团队合作在自然语言处理顶级会议 EMNLP2022 上发表基于 Prompt-Tuning 的小样本机器阅读理解算法 KECP(Knowledge Enhanced Contrastive Prompt-tuning)。KECP 是一种面向机器阅读理解的小样本学习算法,采用 Prompt-Tuning 作为基础学习范式,在仅需要标注极少训练数据的情况下,在给定文章中抽取满足要求的文本作为答案。
论文:
Jianing Wang*, Chengyu Wang*, Minghui Qiu, Qiuhui Shi, Hongbin Wang, Jun Huang, Ming Gao. KECP: Knowledge-Enhanced Contrastive Prompting for Few-shot Extractive Question Answering. EMNLP 2022
背景
在预训练语言模型广泛应用的背景下,传统的机器阅读理解(Machine Reading Comprehension)任务通常需要大量的标注数据来微调模型(例如 BERT)。机器阅读理解任务旨在给定一篇文章(Passage)和一个问题(Question),从文章中寻找对应问题的答案(Answer)。通常情况下,我们假设答案来自于文章中的子片段,这一任务可以进一步被称为抽取式阅读理解,或抽取式问答(Extractive Question Answering)。这一任务在大量深度学习应用中有广泛的应用场景,例如任务型对话系统等。
传统的抽取式问答采用序列标注或指针网络的方法,获得答案在给定文章的区间,其学习范式如下图(a)所示:
然而,这种方法需要重头开始学习 Preduction Head 的参数,在小样本场景下容易过拟合。最近 Prompt-Tuning(即提示微调)相关方法的提出缓解了预训练语言模型在低资源场景下的过拟合问题。特别地,对于 BERT 类模型,其通常是将下游任务目标转换为预训练目标(例如 Masked Language Modeling),以充分复用预训练阶段的先验知识。受到这个启发,我们将抽取式阅读理解转换为基于 BERT 的生成任务,如上图(b)。
算法概述
我们提出的 KECP(Knowledge Enhanced Contrastive Prompt-tuning)模型综合利用了模型表示的知识增强和对比学习技术,提升了小样本学习场景下的机器阅读理解准确度,模型架构图如下:
模型输入
首先,我们将问题(Question)转换为陈述句,并通过一些启发式规则将问题变为类似完形填空任务。例如,我们可以将问题
What was one of the Normans’major exports?
变为
[MASK] [MASK] [MASK] was one of the Normans’major exports.
其中[MASK]为待预测的 Token。最后,我们将这一陈述句和文章进行拼接在一起,形成统一的输入序列:
知识增强的语义表达
因为训练样本很少时,模型的推理能力有限;因此,我们提出了知识注入方法,即给定一个知识库(例如 Wikidata5M),我们使用实体链指工具识别出文章(Passage)中所有实体。在 KECP 算法中,我们提出了 Passage Knowledge Injection 模块,将预训练知识库实体表征与 Word Embedding 表征向量通过门控单进行向量融合:
为了避免注入过多知识引起知识噪音(Knowledge Noise)问题,我们将融合了知识的文章表征信息聚集到问题部分挑选的 Token 中。例如,在前述示例中,我们挑选了名词“Norman Major Exports”,我们可以通过 Self-Attention 模型将文章中的实体融合向量进一步融合到这些选定的 Token 中:
这样,我们能获得更好的文本表征。
对比学习增强的模型训练
在获得新的表征向量后,我们将这些表征喂入 BERT 模型中,进行模型的训练。我们复用了预训练任务目标 Masked Language Modeling(MLM)。为了提高模型效果,我们采用对比学习对学习目标进行增强。在 KECP 的对比学习模块中,正样本为 Ground Truth,负样本为通过知识库检索到文章中的一些错误的实体(这些实体可能会对模型预测产生混淆),损失函数如下:
KECP 协同最小化 MLM 和对比学习损失,得到最终的机器阅读理解模型。
算法精度评测
为了评测 KECP 算法的精度,我们在一些常用的机器阅读理解数据集上,随机采样 16 个样本进行训练,结果如下:
结果可以证明,KECP 在这些数据集上获得不错的效果。在未来,我们会拓展 KECP 到到 BART、T5 等生成式模型上,训练更加通用的生成式阅读理解模型。为了更好地服务开源社区,KECP 算法的源代码即将贡献在自然语言处理算法框架 EasyNLP 中,欢迎 NLP 从业人员和研究者使用。
EasyNLP 开源框架:https://github.com/alibaba/EasyNLP
参考文献
- Chengyu Wang, Minghui Qiu, Taolin Zhang, Tingting Liu, Lei Li, Jianing Wang, Ming Wang, Jun Huang, Wei Lin. EasyNLP: A Comprehensive and Easy-to-use Toolkit for Natural Language Processing. EMNLP 2022
- Xiang Lisa Li, Percy Liang. Prefix-Tuning: Optimizing Continuous Prompts for Generation. ACL/IJCNLP 2021: 4582-4597
- Ori Ram, Yuval Kirstain, Jonathan Berant, Amir Globerson, Omer Levy. Few-Shot Question Answering by Pretraining Span Selection. ACL/IJCNLP 2021: 3066-3079
- Rakesh Chada, Pradeep Natarajan. FewshotQA: A simple framework for few-shot learning of question answering tasks using pre-trained text-to-text models. EMNLP 2021: 6081-6090
- Mandar Joshi, Danqi Chen, Yinhan Liu, Daniel S. Weld, Luke Zettlemoyer, Omer Levy. SpanBERT: Improving Pre-training by Representing and Predicting Spans. Trans. Assoc. Comput. Linguistics 8: 64-77 (2020)
- Xiao Liu, Kaixuan Ji, Yicheng Fu, Zhengxiao Du, Zhilin Yang, Jie Tang. P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks. CoRR abs/2110.07602 (2021)
论文信息
论文名字:KECP: Knowledge-Enhanced Contrastive Prompting for Few-shot Extractive Question Answering
论文作者:王嘉宁、汪诚愚、邱明辉、石秋慧、王洪彬、黄俊、高明
论文 pdf 链接:https://arxiv.org/abs/2205.03071
作者 | 任雪龙
导读
网络直播功能作为一项互联网基本能力已经越来越重要,手机中的直播功能也越来越完善,电商直播、新闻直播、娱乐直播等多种直播类型为用户提供了丰富的直播内容。随着直播的普及,为用户提供极速、流畅的直播观看体验也越来越重要。
全文6657字,预计阅读时间17分钟。
01 背景
百度 APP 作为百度的航母级应用为用户提供了完善的移动端服务,直播也作为其中一个必要功能为用户提供内容。随着直播间架构、业务能力逐渐成熟,直播间播放指标优化也越来越重要。用户直播资源时,可以快速的看到直播画面是其中一个核心体验,起播速度也就成了直播间优化中的一个关键指标。
02 现状
由于包体积等原因,百度 APP 的 Android 版中直播功能使用插件方式接入,在用户真正使用直播功能时才会将直播模块加载。为解决用户直播功能时需要等待插件下载、安装、加载等阶段及兼容插件下载失败的情况,直播团队将播放、IM 等核心能力抽到了一个独立的体积较小的一级插件并内置在百度 APP 中,直播间的挂件、礼物、关注、点赞等业务能力在另外一个体积较大的二级插件中。特殊的插件逻辑和复杂的业务场景使得 Android 版整体起播时长指标表现的不尽人意。
2022 年 Q1 直播间整体起播时长指标 80 分位在 3s 左右,其中二跳(直播间内上下滑)场景在 1s 左右,插件拆分上线后通过观察起播数据发现随着版本收敛,一跳进入直播间携带流地址(页面启动后会使用该地址预起播,与直播列表加载同步执行)场景起播时有明显的增长,从发版本初期 1.5s 左右,随版本收敛两周内会逐步增长到 2.5s+。也就是线上在直播间外直播资源进直播间时有很大一部分用户在后还需要等待 3s 甚至更长时间才能真正看到直播画面。这个时长对用户使用直播功能有非常大的负向影响,起播时长指标急需优化。
03 目标
△起播链路
起播过程简单描述就是用户直播资源,打开直播页面,请求起播地址,调用内核起播,内核起播完成,内核通知业务,业务起播完成打点。从对内核起播时长监控来看,直播资源的在内核中起播耗时大约为 600-700ms,考虑链路中其他阶段损耗以及二跳(直播间内上下滑)场景可以在滑动时提前起播,整体起播时长目标定位为1.5 秒;考虑到有些进入直播间的位置已经有了起播流地址,可以在某些场景省去 “请求起播地址” 这一个阶段,在这种直播间外已经获取到起播地址场景,起播时长目标定为 1.1 秒。
04 难点
特殊的插件逻辑和复杂的业务场景使得 Android 版每一次进入直播的起播链路都不会完全一样。只有一级插件且二级插件还未就绪时在一级插件中请求直播数据并起播,一二级插件都已加载时使用二级插件请求直播数据并处理起播,进直播间携带流地址时为实现秒开在 Activity 启动后就创建播放器使用直播间外携带的流地址起播。除了这几种链路,还有一些其他情况。复杂的起播链路就导致了,虽然在起播过程中主要节点间都有时间戳打点,也有天级别相邻两个节点耗时 80 分位报表,但线上不同场景上报的起播链路无法穷举,使用现有报表无法分析直播大盘起播链路中真正耗时位置。需要建立新的监控方案,找到耗时点,才能设计针对性方案将各个耗时位置进行优化。
05 解决方案
5.1 设计新报表,定位耗时点
△一跳有起播地址时起播链路简图
由于现有报表无法满足起播链路耗时阶段定位,需要设计新的监控方案。观察在打开直播间时有流地址场景的流程图(上图),进入直播间后就会同步创建直播间列表及创建播放器预起播,当直播间列表创建完毕且播放器收到首帧通知时起播流程结束。虽然用户到页面 Activity 的 onCreate 中可能有多个节点(一级插件安装、加载等),页面 onCreate 调用播放器预起播中可能多个节点,内核完成到直播业务收到通知中有多个节点,导致整个起播链路无法穷举。但是我们可以发现,从用户到 onCreate 这个路径是肯定会有的,onCreate 到创建播放器路径也是肯定有的。这样就说明虽然两个关键节点间的节点数量和链路无法确定,但是两个关键节点的先后顺序是一定的,也是必定会有的。由此,我们可以设计一个自定义链路起点和自定义链路终点的查询报表,通过终点和起点时间戳求差得到两个任意节点间耗时,将线上这两个节点所有差值求 80 分位,就可以得到线上起播耗时中这两个节点间耗时。将起播链路中所有核心关键节点计算耗时,就可以找到整个起播链路中有异常耗时的分段。
按照上面的思路开发新报表后,上面的链路各阶段耗时也就比较清晰了,见下图,这样我们就可以针对不同阶段逐个击破。
△关键节点间耗时
5.2 一跳使用一级插件起播
使用新报表统计的重点节点间耗时观察到,直播间列表创建(模版组件创建)到真正调用起播(业务视图就绪)中间耗时较长,且这个耗时随着版本收敛会逐步增加,两周内大约增加 1000ms,首先我们解决这两个节点间耗时增加问题。
经过起播链路观察和分析后,发现随版本收敛,这部分起播链路有较大变化,主要是因为随版本收敛,在二级插件中触发 “业务调用起播” 这个节点的占比增加。版本收敛期,进入直播间时大概率二级插件还未下载就绪或未安装,此时一级插件中可以很快的进行列表创建并创建业务视图,一级插件中在 RecyclerView 的 item attach 到视图树时就会触发起播,这个链路主要是等待内核完成首帧数据的拉取和解析。当二级插件逐渐收敛,进入直播间后一级插件就不再创建业务视图,而是有二级插件创建业务视图。由于二级插件中业务组件较多逐个加载需要耗时还有一级到二级中逐层调用或事件分发也存在一定耗时,这样二级插件起播场景就大大增加了直播间列表创建(模版组件创建)到真正调用起播(业务视图就绪)中间耗时。
5.2.1 一跳全部使用一级插件起播
基于上面的问题分析,我们修改了一跳场景起播逻辑,一跳全部使用一级插件起播。一级插件和二级插件创建的播放器父容器 id 是相同的,这样在一级插件中初始化播放器父容器后,当内核首帧回调时起播过程就可以结束了。二级插件中在初始化播放器父容器时也会通过 id 判断是否已经添加到视图树,只有在未添加的情况(二跳场景或一跳时出现异常)才会在二级中进行兜底处理。在一级插件中处理时速度可以更快,一级优先二级兜底逻辑保证了进入直播间后一定可以顺利初始化视图。
5.2.2 提前请求接口
使用由一起插件处理起播优化了二级插件链路层级较多问题,还有一个耗时点就是进直播间时只传入了房间 room_id 未携带流地址场景,此时需要通过接口请求获取起播数据后才能创建播放器和起播。为优化这部分耗时,我们设计了一个直播间数据请求管理器,提供了缓存数据和超时清理逻辑。在页面 onCreate 时就会触发管理器进行接口请求,直播间模版创建完成后会通过管理器获取已经请求到的直播数据,如果管理器接口请求还未结束,则会复用进行中请求,待请求结束后立刻返回数据。这样在进直播间未携带流数据时我们可以充分利用图中这 300ms 时间做更多必要的逻辑。
5.3 播放器Activity外预起播
通过进直播间播放器预创建、预起播、一跳使用一级插件起播等方案来优化进入直播间业务链路耗时后,业务链路耗时逐渐低于内核部分耗时,播放器内核耗时逐渐成为一跳起播耗时优化瓶颈。除了在内核内部探索优化方案,继续优化业务整个起播链路也是一个重要方向。通过节点间耗时可以发现,用户到 Activity 页面 onCrete 中间也是有 300ms 左右耗时的。当无法将这部分耗时缩到更短时,我们可以尝试在这段时间并行处理一些事情,减少页面启动后的部分逻辑。
一级插件在百度 APP 中内置后,设计并上线了插件预加载功能,上线后用户通过直播资源进入直播间的场景中,有 99%+ 占比都是直播一级插件已加载情况,一级插件加载这里就没有了更多可以的操作空间。但将预起播时机提前到用户处,可以将内核数据加载和直播间启动更大程度并行,这样来降低内核耗时对整个起播耗时影响。 △播放器在直播间外起播示意图
如上图,新增一个提前起播模块,在用户后与页面启动并行创建播放器起播并缓存,页面启动后创建播放器时会先从提前起播模块的缓存中尝试取已起播播放器,如果未获取到则走正常播放器创建起播逻辑,如果获取到缓存的播放器且播放器未发生错误,则只需要等待内核首帧即可。
播放器提前起播后首帧事件大概率在 Activity 启动后到达,但仍有几率会早于直播业务中设置首帧监听前到达,所以在直播间中使用复用内核的播放器时需要判断是否起播成功,如果已经起播成功需要马上分发已起播成功事件(含义区别于首帧事件,防止与首帧事件混淆)。
提前起播模块中还设计了超时回收逻辑,如果提前起播失败或 5s (暂定)内没有被业务复用(Activity 启动异常或其他业务异常),则主动回收缓存的播放器,防止直播间没有复用成功时提前创建的播放器占用较多内存及避免泄漏;超时时间是根据线上大盘起播时间决定,使用一个较大盘起播时间 80 分位稍高的值,防止起播还未完成时被回收,但也不能设置较长,防止不会被复用时内存占用较多。
通过提前起播功能,实验期命中提前起播逻辑较不进行提前起播逻辑,整体起播耗时 80 分位优化均值:450ms+。
5.4直播间任务打散
△内核首帧分发耗时
业务链路和内核链路耗时都有一定优化后,我们继续拆解重点节点间耗时。内核内部标记首帧通知到直播业务真正收到首帧通知之间耗时较长,如上图,线上内核首帧分发耗时 80 分位均值超过 1s,该分段对整体起播耗时优化影响较大。内核首帧是在子线程进行标记,通知业务时会通过主线程 Handler 分发消息,通过系统的消息分发机制将事件转到主线程。
通过排查内核标记首帧时间点到业务收到首帧通知事件时间点之间所有主线程任务,发现在首帧分发任务开始排队时,主线程任务队列中已有较多其他任务,其他事件处理时间较长,导致首帧分发排队时间较久,分发任务整体耗时也就较长。直播业务复杂度较高,如果内核首帧分发任务排队时直播间其他任务已在队列中或正在执行,首帧分发任务需要等直播任务执行完成后才能执行。
通过将直播间启动过程中所有主线程任务进行筛查,发现二级插件的中业务功能较多,整体加载任务执行时间较长,为验证线上也是由于二级业务任务阻塞了首帧分发任务,我们设计了一个二级组件加载需要等待内核首帧后才能进行的实验,通过实验组与对照组数据对比,在命中实验时首帧分发耗时和起播整体耗时全部都有明显下降,整体耗时有 500ms 左右优化。
通过实验验证及本地对起播阶段业务逻辑分析,定位到直播间各业务组件及对应视图的预加载数量较多且耗时比较明显,这个功能是二级插件为充分利用直播间接口数据返回前时间,二级插件加载后会与接口请求并行提前创建业务视图,提起初始化组件及视图为接口完成后组件渲染节省时间。如果不预创建,接口数据回来后初始化业务组件也会主动创建后设置数据。但将所有预创建任务全部串行执行耗时较长,会阻塞主线程,页面一帧中执行太多任务,也会造成页面明显卡顿。
发现这个阻塞问题后,我们设计了将预创建视图任务进行拆分打散,将一起执行的大任务拆分成多个小任务,每个组件的初始化都作为一个单独任务在主线程任务队列中进行排队等待执行。避免了一个大任务耗时特别长的问题。该功能上线后,整个二级插件中的组件加载大任务耗时降低了 40%+。
5.5 内核子线程分发首帧
由于主线程消息队列中任务是排队执行的,将阻塞首帧分发事件的大任务拆分成较多小任务后,还是无法解决首帧事件开始排队时这些小任务已经在主线程任务队列中排队问题。除了降低直播业务影响,还可以通过加快内核任务分发速度,使首帧分发耗时降低。需要设计一个在不影响内核稳定性与业务逻辑情况下内核首帧事件如何避免主线程排队或快速排队后被执行的方案。
为解决上面的问题, 我们推动内核,单独增加了一个子线程通知业务首帧事件能力。业务收到子线程中首帧回调后通过 Handler 的 postAtFrontOfQueue() 方法将一个新任务插到主线程任务队列最前面,这样主线程处理完当前任务后就可以马上处理我们新建的这个任务,在这个新任务中可以马上处理播放器上屏逻辑。无需等待播放内核原本的主线程消息。
主线程任务前插无法打断新任务排队时主线程中已经开始执行的任务,需要正在执行任务结束后才会被执行。为优化这个场景,内核通过子线程通知首帧后,播放器中需要记录这个状态,在一级插件及二级插件中的直播间业务任务执行开始前后,增加判断播放器中是否已经收到首帧逻辑,如果已经收到,就可以先处理上屏后再继续当前任务。
通过直播内核首帧消息在主线程任务队列前插和业务关键节点增加是否可上屏判断,就可以较快处理首帧通知,降低首帧分发对起播时长影响。
5.6 起播与完载指标平衡
直播间起播优化过程中,完载时长指标(完载时长:用户到直播间核心功能全部出现的时间,其中经历页面启动,直播间列表创建,二级插件下载、安装、加载,直播间接口数据请求,初始化直播间功能组件视图及渲染数据,核心业务组件显示等阶段)的优化也在持续进行。直播间二级插件是在使用二级插件中的功能时才会触发下载安装及加载逻辑,完载链路中也注意到了用户到页面 onCreate 这段耗时,见下图。
△页面启动耗时示意图
为优化直播间完载指标,直播团队考虑如果将插件加载与页面启动并行,那么完载耗时也会有一定的优化。直播团队继续设计了二级插件预加载方案,将二级插件加载位置提前到了用户的时候(该功能上线在 5.4、5.5 章节对应功能前)。该功能上线后试验组与对照组数据显示,实验组完载耗时较对照组确实有 300ms+ 优化。但起播耗时却出现了异常,实验组的起播耗时明显比对照组增长了 500ms+,且随版本收敛这个起播劣化还在增加。我们马上很快发现了这个异常,并通过数据分析确定了这个数据是正确的。完载的优化时如何引起起播变化的?
经过数据分析,我们发现起播受影响的主要位置还是内核首帧消息分发到主线程这个分段引起,也就是二级插件加载越早,内核首帧分发与二级组件加载时的耗时任务冲突可能性越大。确认问题原因后,我们做了 5.4、5.5 章节的功能来降低二级组件加载任务对起播影响。由于二级插件中的耗时任务完全拆分打散来缓解二级插件预下载带来的起播劣化方案复杂度较高,对直播间逻辑侵入太大,二级插件提前加载没有完全上线,完载的优化我们设计了其他方案来实现目标。
虽然不能在进入直播间时直接加载二级插件,但我们可以在进入直播间前尽量将二级插件下载下来,使用时直接加载即可,这个耗时相对下载耗时是非常小的。我们优化了插件预下载模块,在直播间外展示直播资源时触发该模块预下载插件。该模块会通过对当前设备网络、带宽、下载频次等条件综合判断,在合适的时机将匹配的二级插件进行下载,插件提前下载后对完载指标有较大优化。除了插件预下载,直播间内通过 5.4 章节直播间二级组件初始化拆分,也将全部组件初始化对主线程阻塞进行了优化,这样接口数据请求成功后可以优先处理影响完载统计的组件,其他组件可以在完载结束后再进行初始化,这个方案也对直播完载指标有明显优化。
除了以上两个优化方案,直播团队还在其他多个方向对完载指标进行了优化,同时也处理了完载时长与起播时长的指标平衡,没有因为一个指标优化而对其他指标造成劣化影响。最终实现了起播、完载指标全部达到目标。
06 收益
△2022 Android 端起播耗时走势
经过以上多个优化方案逐步迭代,目前 Android 端最新版本数据,大盘起播时间已经由 3s+ 降到 1.3s 左右;一跳带流地址时起播时长由 2.5s+ 左右降低到 1s 以内;二跳起播时长由 1s+ 降低到 700ms 以内,成功完成了预定目标。
07 展望
起播时长作为直播功能一个核心指标,还需要不断打磨和优化。除了业务架构上的优化,还有优化拉流协议、优化缓冲配置、自适应网速起播、优化 gop 配置、边缘节点加速等多个方向可以探索。百度直播团队也会持续深耕直播技术,为用户带来越来越好的直播体验。
——END——
推荐阅读:
iOS SIGKILL 信号量崩溃抓取以及优化实践
如何在几百万qps的网关服务中实现灵活调度策略
深入浅出DDD编程
百度APP iOS端内存优化实践-内存管控方案
Ernie-SimCSE对比学习在内容反作弊上应用
质量评估模型助力风险决策水平提升
作者:郑啟龙
摘要:
对于MYSQL的INNODB存储引擎的索引,大家是不陌生的,都能想到是 B+树结构,可以加速SQL查询。但对于B+树索引,它到底“长”得什么样子,它具体如何由一个个字节构成的,这些的基础知识鲜有人深究。本篇文章从MYSQL行记录开始说起,层层递进,包括数据页,B+树聚簇索引,B+树二级索引,最后在文章末尾给出MYSQL索引的建议。文章涉及较多基础知识,内容较为枯燥,因此采用较多的图片补充说明,希望能对读者有帮助。
A. 一条记录存储格式:COMPACT行记录结构
mysql是关系型数据库,每一行记录都是表结构定义的关系的 显示表达。在脑中很直观地想到,记录存储时也可能按行存储。
的确,mysql是这么存储一条行记录的。但会添加一些额外信息,来补充行记录信息。
有一个概念可能大家不熟悉,是【变长字段】。mysql数据库类型中的 VARCHAR(M), VARBINARY(M), 各种TEXT,BLOB类型,这些类型的数据长度是可变的,称 数据类型为可变长类型的列 为 变长字段。
另外,mysql会默认为行记录添加一些列(隐藏列)。上图补充这些隐藏列之后,完整行记录的结构如:
DB_ROW_ID: 唯一标识一条记录,在表中未设置主键 或 未有不允许为NULL的UNIQUE键时,则MYSQL新增该隐藏列作为主键。 DB_TRX_ID: 事务ID。 DB_ROLL_PTR: 回滚指针。
下面再详细的铺开 ,关于记录的额外信息 的具体内容。
通过真实的数据库表的行数据,来强化下上面的概念。 首先新增一个表,并在表中insert两条记录。
做一个简单的查询,验证数据正常写入。
分析这两行数据的存储记录。
第一行记录:
第二行记录:
应该会注意到,变长字段长度列表 与 NULL值列表都是逆序存放的。 原因是:这样可以使得记录中位置靠前的字段 和 它们对应的字段长度信息在内存中的距离更近,可能会提高 高速缓存的命中率。
B. 盛放记录的盒子:数据页
为了更清楚的理解 数据页结构 以及 下文中的索引,更换一个带主键的表。
做一个简单的查询,验证数据正常写入。
根据行记录结构中的next_recrod属性的含义,多条行记录是以单向链表的形式存储。mysql为了后续更好的查询,单向链表上的记录是按照主键顺序排列的。 上述这四条记录,可以显示的画成:
假如删除其中c1=2这条数据,则单向链表变更如下。 其中变化点为 c1=2 这条数据中,deleted_flag变更成0, next_record=0,但并没有从磁盘上直接清除掉,head_no也未清除。第一条记录的next_record 指向了第三条记录。
当我们查询数据时,如果数据以行记录的形式一条一条从磁盘加载到内存中,那么因为IO过多的原因,整体性能肯定较为低效。 因此mysql规定,磁盘与内存交换数据的基本单位是一个页大小。这个页大小 默认是16K。 根据页中存储的数据类型不同,页也分成许多类型。对于存储行记录的页,称为索引页(Index Page),也称为数据页。
那么接下来我们看看,数据页的结构如何,一条条行记录如何存放在数据页中。先上个图。
从上图中,我们可以猜到,数据页总共分成7个模块,目前咱们只关心 User Records 部分,它存储的就是用户真实的行记录。 但是一个数据页的空间总共是16K,不会自动增大空间,随着User Records 模块中的行记录越来越多,那么肯定有其他模块的空间就越来越小。 这个模块是 Free Space,是页中尚未使用的空间。更新一下上面这个图,补充 Free Space的内容。随着User Records中行记录的增加,Free Space空间则越来越小。
在一个数据页中,除了真实的行记录之外,还有两条固定的伪记录。 其中一条记录称为 infimum 【[ɪnˈfaɪməm] ,下确界】行记录,规定是数据页中记录的最小值。 infimum记录特别简单,仅包含了 记录头信息(5字节) + 真实记录数据(8字节),其中【69 6E 66 69 6D 75 6D 00】16进制转换成对应的单词,就是【infimum】。
另外一条记录称为 supremum【[sə’priməm],上确界】行记录,规定是数据页中记录的最大值。 supremum记录同样特别简单,仅包含了 记录头信息(5字节) + 真实记录数据(8字节),其中【73 75 70 72 65 6D 75 6D】16进制转换成对应的单词,就是【supremum】。
再更新一版数据库页结构, 补充上infimum 与 supremum。
既然规定了页面中的最小记录 与 最大记录,理所应当,上文中串联各个行记录的单向链表,则应该有一个固定的头部 与 固定的尾部。 更新一下单链表的图。注意下infimum 与 supremum中的几个关键值。
infimum: n_owned=1,表示是某一个分组的最后一条记录,当前分组共1条记录;record_type=2; next_record=第一条真实行记录的真实值的相对位置。 supremum: n_owned=5,表示是某个分组的最后一条记录,当前分组共5条记录;record_type=3; next_record=0,表示记录是本数据页中最后一条记录。
OK,到现在数据页中完整的单链表已经形成了。 思考一个问题,如何根据主键值,在数据页中的单链表如何查找到相应的数据。 最直接的做法是:从 infimum记录开始,沿着单链表的顺序不断的向后查找,直到supremum结束。在这期间,找到满足条件的记录就返回,找不到则不返回。
一个数据页默认大小是16K,用于存储真实行记录的空间超过 98%以上。也就是说,一个数据页中在行记录填充满的情况下,行记录的数量是较多的(当然与行记录大小有关)。 如果每次查询都从单链表的infimum记录 一直到 supremum记录,肯定是无法接受的,很有必要对此现状进行优化。 由此,引出了数据页中的另一个模块,Page Directory,页目录。
首先返回看下上面完整单链表中,infimum记录 与 supremum记录中的两个值,n_owned。这个值分别为 n_owned=1 与 n_owned=5。
参考下n_owned的定义,它是:【页面分组之后,每个组最后一条行记录中该值等于本组内的记录数量。本组内其他记录该值都等于0。】 对于上面的单链表,其它行记录的owned值 都为零。也就是说,infimum单条记录作为一个组,剩余的四条行记录+supremum记录作为一个组。 mysql规定:
对于infimum记录所在的分组只能有1条记录,也就是它本身。
对于supremum记录所在的分组的记录数在1~8条之间。
其它的分组记录的条数范围,在4~8条之间。
将每个组中 最后一条记录在页面中的地址偏移量(该记录的真实数据与数据页中第0个字节之间的距离)单独提取出来,以倒序存储到数据页中的固定模块中。 这个模块,就称为:Page Directory。Page Directory中存储的地址偏移量,也称为Slot 【[slɒt], 槽】,每个Slot两字节。【可以想想为啥是两字节?】
再次更新下数据页结构图。
目前的只有四条记录,两个分组,数量太少了。我们继续往表中继续增加一些记录。
在不断的插入新行记录时,因此不同类型分组数量的约束,所以分组也会增加。这个过程如下:
在初始情况下,一个数据页中只会有 infimum 与 supremum 这两条记录,它们分别属于两个组。此时Page Directory 也只会有两个slot,分别代表infimum的地址偏移量 与 supremum的地址偏移量。
之后每新增一条行记录,都会从Page Directory中找到对应的记录的主键值 比 待新增记录的主键值大 并且差值最小的slot【slot是一个组内最大的那条记录在页面中的地址偏移量,通过slot可以快速找到对应记录的主键值】, 然后把该slot对应的记录的 n_owned值加1,表示本组内新增了一条记录,直到该组中的记录数等于8个。
当一个组中的记录数等于8后,再插入一条记录,会将组中的记录拆分成两个组,其中一个组中是4条记录,另外一个组中是5条记录。拆分过程中,会新增一个slot,记录这个新增分组中最大的那条记录的地址偏移量。
现在来看看下,目前该数据页中的行记录的分组情况。
来演绎一个根据主键查询行记录的例子。假如想查询主键值 ,也就是C1=6的行记录。通过二分法查找,过程如下:
设置low=0,high=4。计算中间slot的位置,(0 + 4) / 2 = 2, 通过slot 2 查询到对应的主键值等于8。因为8 > 6, 所以设置high = 2, low = 0不变。
重新计算中间slot的位置,(0 + 2)/ 2 = 1, 查看 slot 1对应记录的主键值为4。又因为 4 < 6, 所以设置low = 1,high 不变。
此时low = 1, high = 2, 所以确定主键值为6的行记录在 slot2 对应的组中。此时找到slot 2的最小一条记录【通过slot 1 的next_record找到slot 2的最小记录】,遍历slot 2中的所有记录即可。
截止目前,数据页模块中,还要三个模块是未知的。回想一下,对于一条行记录,它有 记录头信息 来描述这条行记录的相关信息,那么对于一个数据页,它有对应的头部来记录数据页的相关信息吗?
有的,自然是有的,而且还不少。这个模块就称为 Page Header。
Page Header的结构如下:
主要作用是标识 数据页中记录了多少条记录,Free Space在页面中的地址偏移量,页目录中包含多少slot等等。
额外说下page_direction 与 page_n_direction的含义。
page_direction: 假如新插入的一条记录的主键值比上一条记录的主键值比上一条记录大,我们说这条记录的插入方向是右边,反之则是左边。用来表示最后一条记录插入方向的状态就是page_direction。
page_n_direction: 假设连续几次插入新记录的方向都是一致的,InnoDB会把沿着同一个方向插入记录的条数记下来,这个条数就用PAGE_N_DIRECTION这个状态表示。 当然,如果最后一条记录的插入方向改变了的话,这个状态的值会被清零重新统计。
到此为止,仅剩下两个模块了,加油啊。
上文中的Page Header 是专门针对数据页记录的各种状态信息。但数据页 仅仅是多种页类型中的一种,其它的还有例如undo日志页,溢出页,存储段信息页,存储区信息页等。 因此mysql 使用了File Header 来描述各种页的通用信息。
从fil_page_prev 与 fil_page_next 两个属性可以联想到,不同页之间是有关联的,而且是以双向链表的形式。
最后一个模块,File Trailer 【 [ˈtreɪlə(r)],挂车】。
InnoDB存储引擎会把数据存储到磁盘上,但是磁盘速度太慢,需要以页为单位把数据加载到内存中处理,如果该页中的数据在内存中被修改了,那么在修改后的某个时间需要把数据同步到磁盘中。
但是在同步了一半的时候中断电了怎么处理呢?此时就需要靠 File Trailer 模块中数据起作用。
展示下完整的数据页结构。
盗用一下网上的一个很好的数据页图。
C. 快速查询的秘籍:B+树索引
上文在介绍File Header时,我们特别说明了里面的两个数据:FIL_PAGE_PREV,指向前一个页号。FIL_PAGE_NEXT, 指向后一个页号。由此可以得出,多个数据页之间的数据结构是双链表。
上文使用的数据共有16条,为了演示这个双链表的效果,现在假设【仅仅是假设】每个页中存放不超过4条行记录。则上文的16条记录,形成的数据页双链表结构如下图【此处省略了许多非必要展示的字段】。
从上面这个链表,可以得到以下结论:
双向链表的页号并不保证是连续的。
下一个数据页中用户记录的主键值必须大于上一个页中用户记录的主键值。【在依次写入主键数据不连续的行记录时,会发生页中数据的迁移。】
从目前的双向链表结构中,想要根据主键值查找记录,也只能是从第一页开始,一页一页的依次查找。虽然在一个数据页中,可以根据 Page Directory进行快速的二分查找,但总体效率肯定不尽人意。得优化。
我们注意到,【下一个数据页中用户记录的主键值必须大于上一个页中用户记录的主键值】。因此,首先进行第一步改进。 维护一个目录项,目录项中记录某个页中主键的最小值以及页号,各个目录项再以单向链表的形式链接起来。这样就可以根据主键查询目录项,得到满足的条件页,再进入相应的页中查询行记录即可。
到现在看看,目录项是不是也很像行记录,只是它的列值是主键与页号。那把这些目录项维护成在一个页中看看效果。毫无违和感,浑然天成。现在看到的,就是主键索引的雏形了。
目前数据有些少了,继续补充一些数据,再画个图看看。