简介:本文将会从阿里巴巴双11场景出发,分析实时数仓面临的高可用挑战以及针对性设计。

2021年阿里巴巴双11完美落下为帷幕,对消费者来说是一场购物盛宴,对背后的业务支撑技术人来说,更是一场年度大考。在这场大考中,一站式实时数仓Hologres以每秒11.2亿条的高速写入,和每秒1.1亿次的查询峰值(包含点查和OLAP查询),交出了满意的答卷,稳定高效地支撑了阿里巴巴双11核心应用场景。

这是一站式实时数仓Hologres诞生的第5年,也是支撑阿里巴巴双11核心场景的第4年。这也证明实时数仓技术已经开始从幕后走到台前,支撑起更多的在线生产系统,并在性能、稳定性、高可用性等方面经受住了严苛的考验。

本文将会从阿里巴巴双11场景出发,分析实时数仓面临的高可用挑战以及针对性设计。

可用性、成本、复杂度的综合挑战

传统上,实时数仓(数据仓库)是一个非生产系统,主要面向内部客户,支撑实时大屏、实时报表等场景。用户对它的稳定性、可用性的要求相较于订单、购物车这样的生产系统要弱很多,只要能继续使用,即使实时数仓短暂不可用或者有明显波动,影响也不是很大。

而随着实时数仓开始对外提供服务,业务对系统的可用性、稳定性都提出了更高更严苛的要求。特别是如果提供的是to C的服务,那要求就更高了。

举几个Hologres被用在阿里生产系统中的例子:

  1. 阿里的CCO(Customer Chief Officer)通过阿里小蜜来向C端消费者提供查询服务。
  2. 阿里妈妈为广告主(B端)提供广告圈选服务。
  3. 达摩院无人车包裹配送服务。

...

这些系统的最大特点是他们都是生产系统,如果系统不稳定或者不可用,那么影响会非常大。

具体到双11这样的极端场景,在流量洪峰下要做好生产高服务质量、达到高可用对任何系统都是一件极具挑战的事。传统分布式系统是通过副本和隔离机制来实现可用性和一致性,而要实现生产可用的高可用也需要面临一定的取舍和挑战:

  • 面向流量洪峰时的可扩展能力
  • 系统因意外或者故障宕机时的快速恢复能力
  • 主备切换时的数据一致性问题
  • 保证高性能的同时资源隔离能力
  • 多副本隔离带来的资源成本问题
  • .......

通过本文,我们将会介绍,一站式实时数仓Hologers的高可用架构设计和实践,从而达到低成本、可扩展、高可用的生产服务能力。

Hologres高可用架构设计

1.   计算存储分离架构提高系统扩展灵活性

实时数仓技术不管是面向分析型场景还是服务型场景,所处理的数据量级、场景复杂度都远比传统数据库要高,尤其是互联网、电商等行业,活动促销多,大促和日常所处理的流量完全不一样,这就非常考验系统的资源水平扩展能力。

在传统的分布式系统中,常用的存储计算架构有如下三种:

  1. Shared Disk/Storage (共享存储):有一个分布式的存储集群,每个计算节点像访问单机数据一样访问这个共享存储上的数据;这种架构的存储层可以比较方便的扩展,但是计算节点需要引入分布式协调机制保证数据同步和一致性,因此计算节点的可扩展性有一个上限。
  2. Shared Nothing:每个计算节点自己挂载存储,一个节点只能处理一个分片的数据,节点之间可以通信,最终有一个汇总节点把数据进行汇总。这种架构能比较方便的扩展,但是它的缺点是节点failover需要等待数据加载完成之后才能提供服务;并且存储和计算需要同时扩容,不够灵活。扩容后,有漫长的数据rebalance过程。
  3. Storage Disaggregation(存储计算分离架构):存储和Shared Storage类似,有一个分布式的共享存储集群,计算层处理数据的模式和Shared Nothing类似,数据是分片的,每个shard只处理自己所在分片的数据,每个计算节点还可以有本地缓存。

这种存储计算分离的架构好处在于:

  • 一致性处理简单:计算层只需要保证同一时刻只有一个计算节点写入同一分片的数据。
  • 扩展性更灵活:计算和存储可以分开扩展,计算不够扩计算节点,存储不够扩存储节点。这样在大促等场景上会非常灵活。计算资源不够了,马上扩容计算就好了,不需要像Shared Nothing那样做耗时耗力的数据rebalance;也不会出现Shared Nothing那样,出现单机的存储容量瓶颈。
  • 计算节点故障恢复快:计算节点发生failover之后,数据可以按需从分布式的共享存储异步拉取。因此,failover的速度非常快。

在架构上,Hologres采用的是第3种存储计算分离架构,Hologres的存储使用的是阿里自研的Pangu分布式文件系统(类似HDFS)。用户可以根据业务需求进行弹性扩缩容,轻松应对在线系统不同的流量峰值

2.多形态Replication解决数据读写分离

Replication(复制)是实现高可用的必备技术,通过不同形态的Replication设计,快速将数据在节点间、集群间进行复制,实现隔离和SLA保障。

Hologers同时支持了逻辑Replication和物理Replication,下面将会针对Hologres的Replication功能做具体介绍。

1)基于Binlog的逻辑Replication

类似于传统数据库MySQL中的Binlog概念,在Hologres中,Binlog用来记录数据库中表数据的修改记录,比如Insert/Delete/Update的操作,主要应用场景包括:

  1. 数据实时复制、同步场景,典型的场景就是把一张Hologres的行存表复制成一张列存表,行存支持点查点写,列存支持多维分析型需求,同步的逻辑通常由Flink支撑。这个是Hologres在V1.1版本之前的一种典型用法。在Hologres 1.1中支持了行列共存表后,可以一张表满足行存和列存两种需求。
  2. 实现事件的全链路驱动,通过Flink消费Hologres Binlog,实现事件驱动的加工开发,完成ODS向DWD,DWD向DWS等的全实时加工作业。

在Hologres中,逻辑Replication依赖Binlog实现,发生变更的表作为Publication发布变更事件,加工逻辑处理后写入Subscription侧。用户可以订阅一个表的Binlog转成Record,写入到另外一张表里,实现逻辑上的复制功能。这种做法可以天然做到不同Workload的隔离,但是它有两个问题:它是一个最终一致性的模型,很难做到强一致;另一个是它消耗了两份资源,使用两份存储,并且写入链路的资源也得有两份。

因此Hologres也实现了物理Replication。

2)物理Replication

在Hologres中,物理Replication是基于WAL log的复制,我们可以把存储引擎看成是状态机,WAL log是这个状态机的输入。当我们要对某个Shard做Replication的时候,我们会起一个Follower Shard读取当前最新的WAL log进行回放(replay),同时Leader Shard又有新的WAL产生,Follower Shard会从Leader Shard订阅最新的WAL,不断的回放,从而达到和Leader Shard一致的状态。如果需要保证Follower Shard上的可见性,我们可以在读请求中加一个强一致的选项,问一下Follower Shard和Leader Shard之间WAL log的回放差距,等补齐差距后再返回查询结果。

Follower Shard回放WAL log的过程中,对WAL log中指向的数据文件可以进行复制。也可以只进行引用,其中复制的方式称为非共享存储模式,引用的方式称为共享存储模式。

基于此,Hologres实现了3种形态的物理Replication:

1.单实例多副本:一个实例内采用Shard级多副本机制,可用来实现跨进程高可用,读写分离,同时因为副本可动态增加,能轻松支持高并发的读。

2.多实例读写分离:不同的实例之间共享一份存储,实现计算跨机房高可用,通常用于读写分离场景,并支持高并发的读场景

3.多实例容灾:多个实例之间不共享存储,实现计算和存储服务的跨机房高可用,支持读写分离,读的高并发,版本的热升级和存储系统的迁移等功能

  • 单实例多副本

Hologres数据分片单元是Shard,Shard可以有多个副本,但是存储只有一份。平时,查询流量可以被各个副本均摊,从而实现高QPS。当某一个副本failover以后,流量可以快速被导到其他副本。并且Shard的故障恢复非常轻量,只需回放部分WAL,没有数据的复制。基于单实例内多副本机制,可以很方便的实现计算的可扩展性,并快速解决物理机单机failover问题。

应用场景:

  1. 单实例内的查询高可用:当一个Shard所在Worker发生故障时,可以通过前端阶段的重试操作,将请求重定向到副本Shard所在Worker,从而应用异常无感知。
  2. 通过负载均摊,实现更高吞吐:同一份数据由多个Shard共同对外提供服务,不同的查询路由到不同的Shard所在节点,从而实现负载在多个Shard间的均衡,QPS可以显著提升,对于每次查询只访问确定Shard的场景(例如点查场景)提升明显。
  3. 机器故障快速Failover:从Hologres V1.1版本开始,采用全新恢复机制,Shard恢复速度在一分钟以内,可用性进一步增强。

  • 多实例读写分离

和单实例内多副本的Replication相比,跨实例的Replication实现了Meta的物理复制。

Hologres 在V1.1版本,支持了共享存储的多实例部署方案。在该方案中,主实例具备完整能力,数据可读可写,权限、系统参数可配置,而子实例处于只读状态,所有的变更都通过主实例完成,实例之间共享一份数据存储,实例间数据异步实时同步。

应用场景:

1.读写分离:这个方案实现了完整的读写分离功能,保障不同业务场景的SLA,在高吞吐的数据写入和复杂的架构作业、OLAP、AdHoc查询、线上服务等场景中,负载之间物理上完全隔离,不会因写入产生查询的抖动。

2.多类型负载细粒度资源分配:一个主实例可以配置多个只读从实例,实例之间可以根据业务情况配置不同规格,例如使用256Core作为写入和加工实例,512Core作为OLAP只读实例,128Core作为在线Serving实例,32Core作为开发测试实例。

  • 多实例跨城容灾

多实例非共享存储的Replication,可以理解为传统意义上的灾备功能,支持容灾,异地多活,并实现读写分离和读的高并发,同样也可以基于多个实例实现读的高可用。除此之外,还可以进行版本热升级,存储系统迁移。

应用场景:

  1. 灾备:在不同的Region,部署有不同的存储集群(Pangu),数据在同步后会分别保存在不同的存储集群上,当发生某个Region不可用时,异地备份的实例可以继续对外提供服务。
  2. 集群迁移:机房的容量空间总是有限,经常会发生因为不可控原因,需要将实例从某个机房迁移到其他机房,甚至从某个Region迁移到其他Region,用户希望迁移过程尽可能是对业务无感的。因此可以通过Replication机制,实现实例状态在集群间的迁移。
  3. 热升级:热升级过程中,需要业务服务能力不中断,属于高速公路上换发动机的需求,因此需要系统具备某种类似“滚动”升级的能力。通过Replication机制,可以先克隆出一个实例,在新的实例上完成软件版本的升级,再将相关的网络路由等配置接入到新的实例,从而完成无需停机的热升级。

3.调度系统提高节点failover快速恢复能力

分布式环境failover是不可避免的,当failover发生时,需要高效的检测,快速的恢复,这就是调度的范畴。

一个Hologres实例有多个HoloWorker,当某一个HoloWorker发生意外、宕机、failover时,通过Hologres的调度系统,可以快速检测到节点异常,并将异常节点的Service如Frontend、Coordinator、Shard快速调度到另外一个健康的HoloWorker,同时SLB将会将流量导流到新的健康Frontend上。

调度分为计算单元的调度和流量的调度:

1)计算单元的调度

计算单元的调度分为Pod的调度、Pod内子进程调度以及Actor的调度

  • Pod的调度利用了K8S的能力,Hologres中被K8S调度的单元是HoloWorker;
  • Pod内子进程调度以及Actor的调度是Hologres分布式调度模块HoloFlow提供的能力。

Hologres中两种类型的计算单元需要被调度,一类是以子进程模式提供Service,例如Frontend;另一类是以Actor模式提供的Service,例如某一个分片的数据服务Shard。HoloFlow提供了这两类服务的健康检测以及调度的能力。

2)流量的调度

流量的调度又分为外部流量和内部流量的调度。

  • 外部流量即入口流量,这部分调度是SLB提供的能力,Hologres会定时监测Frontend的健康状态,一旦某个Frontend不健康了,流量就会从SLB上摘除。
  • 内部流量Hologres提供了内部的健康检测和服务发现机制,例如StoreMaster提供了Shard的健康检测和服务发现机制,一旦某个Shard不健康,Coordinator就会把流量导到这个Shard健康的Replica上。

通过Hologres的调度系统,实现了节点故障、Failover的快速检测以及自动调度恢复能力,满足业务的稳定性需求,提高系统可用性。

4.多层次隔离轻松应对不同业务SLA

随着实时数仓在生产系统越来越广泛的应用,不同的业务也有着不同的SLA诉求,比如双11时,老板和运营对交易数据的查询需求比较高,物流端又希望物流订单能实时高效刷新,开发又希望数据能快速写入,不要影响后面的数据查询和分析....

具体到Hologres,一个实例支持不同的Workload,包括点查点写,批量导入,交互式分析等。那么不同Workload的SLA需要被保障,例如批量导入不能影响交互式分析的延时,交互式分析的请求不能影响实时写入的实效性等;Hologres也支持多租户同时使用,不同租户之间也不能相互影响;

以上描述的场景都是隔离的范畴,相对来说隔离级别越高,成本越大,资源利用率越低。在进程内部实现低成本可用的隔离是一个很有技术挑战的事情。

Hologres实现了多个层次的隔离手段。如下图是上面介绍的Replication(复制)和隔离的关系,复制本质上是在不同的机器/容器中服务同一份数据(或其复本),所以本质上是一种物理隔离。在物理隔离外,Hologres还支持资源组隔离、调度组和(SchedulingGroup)隔离,用户可以在成本和SLA上做tradeoff,满足不同用户对隔离的需求。

1)物理机和容器隔离

在物理机和容器隔离上,Hologers是通过k8s来部署,利用k8s的Node Selector/Affinity以及Taints/Tolerations等功能,可以比较方便的实现实例和实例间容器的隔离。对于一些对SLA要求非常高的客户,我们还可以对机器单独打标,只允许某一个实例的容器调度到打标的机器上,从而实现机器级别的隔离,防止其他实例的干扰。

2)资源组隔离

在Hologres中,多租户的隔离需求是通过资源组来实现的。Hologres的资源组隔离本质上是线程级别的隔离。实例内的Worker可以按照CPU、内存、IO划分为不同的资源组。不同的用户加入到不同的资源组,限制每个用户使用的资源上限,以保证用户之间的作业互不影响。

例如资源组(1)有50%的资源,资源组(2)有30%的资源,资源组(3)有20%的资源。我们把用户A绑定的资源组(一)上,用户B绑定在资源组(2)上,用户C和D绑定到资源组(3)上。这样用户A,B.C发起的请求就会分别调度到不同的资源组。

通过资源组的隔离,实现实例内的资源隔离。这种隔离的优点是能够在一个实例内实现不同用户的隔离,保证用户间的作业不相互影响。这种隔离是一种软隔离,在隔离效果上是不如基于replication的物理隔离的。所以资源组隔离更适合不同用户的OLAP查询隔离等场景,而基于replication的物理隔离更适合线上服务。

3)SchedulingGroup隔离

通常来说,2)中的线程级别隔离模型会有如下问题:

  • 在操作系统层面:线程切换是一个不小的开销。为了把因为等待IO而空闲的CPU利用起来,需要把很多CPU浪费在线程切换上。测试发现,严重的时候线程切换能浪费掉一半以上的CPU;
  • 线程的数目很难掌握:不同的query、不同的数据、不同的cache命中率,被IO阻塞的可能性差异会非常大,以至于需要的线程数差别非常大。这种情况下,使用固定线程数目的线程池是很难受的。线程多了会引起多余的切换,加剧切换的开销;线程少了则可能没法把空闲的CPU都利用起来。而相比于线程切换,线程的创建和销毁会带来更大的开销,所以想要通过动态创建线程来保持恰当的线程数,这也是不太可能的;

理想的方案是能有一种轻量级的调度单元,功能类似于线程,但是创建/销毁和调度/切换的开销要小得多。这样的话:

  • 我们可以根据业务逻辑的需要,创建足够多的“线程”去并发使用CPU,而不必担心切换的开销大、或者CPU用不满;
  • 当需要业务逻辑需要使用CPU时,直接根据并发度的需要去创建N个这样的“线程”,用完即销毁。这样就能使业务逻辑灵活控制任务的并行度,不必受制于底层框架;

根据上面的设计理念,Hologres在自研调度系统HOS中,通过一个轻量级调度单元EC来实现。

SchedulingGroup隔离利用了HOS EC调度的能力,同一个Query有多个EC执行,这些EC可以被归类到一个SchedulingGroup,不同的SchedulingGroup可以用公平的策略瓜分时间片。

SchedulingGroup隔离保证了当系统中同时跑一个大Query(分析型)和一个小Query(点查)的时候,小Query不至于因为抢不到CPU被大Query block住。SchedulingGroup隔离本质上是协程级别的隔离,是Hologres的核心竞争力之一。

Hologres高可用在双11的落地实践

Hologers的高可用技术今年也稳定支持了阿里巴巴双11的核心业务场景,下面来做一一介绍。

1)业务双联路+读写实例分离(DT团队实践)

DT大淘系数据是阿里巴巴集团典型的数据中台,负责天猫、淘宝、聚划算等业务大促及日常行业看数需求,通过天猫/淘宝营销活动分析产品,支持决策层和小二在大促期间进行数据分析及决策。

随着业务增长和产品的不断迭代,数据团队也面临更复杂的分析需求,技术团队在保障数据实时性、准确性的同时,还要面临更高压力的写入,在保障整体数据链路的稳定性和整体产品的高可用上面临更严格的考验。

在高可用场景上,今年DT引入了Hologres的读写分离能力,并结合全链路的主备双链路,在降低单库出问题概率的同时构建异地主备容灾,建立产品核心指标的“复活甲”,通过秒级切换的高可用容灾方案,高吞吐写入和灵活查询互不干扰,分析查询QPS增长80%的同时,查询抖动明显减少,让业务拥有底气和信心去应对随时可能出现的不可控风险,为整个产品和业务决策分析提供稳定支持,

2)双链路容灾+读写分离(CCO团队实践)

CCO是阿里巴巴集团的客户体验事业部,支持的场景包括服务资源调度、实时数据监控等。“客户第一”价值观落地的组织保障,是整个经济体客户体验的神经网络,也是触达消费者和商家的最前线。

随着业务的发展,以及行业的整体业务趋势,以及相应商家和消费者们更加实时和稳定的服务请求。去年是业务上做了双链路写入和存储冗余来保证高可用。今年双11使用了Hologres原生的 只读实例 和 容灾 高可用方案下掉了业务的双链路,省去备用数据链路上实时任务开发维护、数据比对的人力投入,减少链路切换时的数据不一致等,整体开发人力成本减少200人日,环比去年降低50%以上;减少了100+用于实时重保的备份链路作业,减少实时计算资源2000CU。

总结

在过去一年,Hologres引入了多副本、资源隔离、读写分离等多种能力,并在今年阿里巴巴核心应用场景中得到了很好的应用,实现了生产高可用。

随着实时数仓技术被生产系统的广泛使用,业务对高可用的要求也越来也严苛。我们希望通过分享Hologres的高可用设计原理和应用实践,与行业互通有无,共同为社会的高度发展添砖加瓦。

Hologres是阿里云自研的一站式实时数仓,这个云原生系统融合了实时服务和分析大数据的场景,全面兼容PostgreSQL协议并与大数据生态无缝打通,能用同一套数据架构同时支持实时写入实时查询以及实时离线联邦分析。它的出现简化了业务的架构,为业务提供实时决策的能力,让大数据发挥出更大的商业价值。从阿里集团诞生到云上商业化,随着业务的发展和技术的演进,Hologres也在持续不断优化核心技术竞争力,为了让大家更加了解Hologres,我们计划持续推出Hologres底层技术原理揭秘系列,从高性能存储引擎到高效率查询引擎,高吞吐写入到高QPS查询等,全方位解读Hologres,请大家持续关注!

原文链接

本文为阿里云原创内容,未经允许不得转载。

技术揭秘:从双11看实时数仓Hologres高可用设计与实践的更多相关文章

  1. 基于Flink构建全场景实时数仓

    目录: 一. 实时计算初期 二. 实时数仓建设 三. Lambda架构的实时数仓 四. Kappa架构的实时数仓 五. 流批结合的实时数仓 实时计算初期 虽然实时计算在最近几年才火起来,但是在早期也有 ...

  2. HBase实战 | 知乎实时数仓架构演进

    https://mp.weixin.qq.com/s/hx-q13QteNvtXRpNsE5Y0A 作者 | 知乎数据工程团队编辑 | VincentAI 前线导读:“数据智能” (Data Inte ...

  3. (转)用Flink取代Spark Streaming!知乎实时数仓架构演进

    转:https://mp.weixin.qq.com/s/e8lsGyl8oVtfg6HhXyIe4A AI 前线导读:“数据智能” (Data Intelligence) 有一个必须且基础的环节,就 ...

  4. flink实时数仓从入门到实战

    第一章.flink实时数仓入门 一.依赖 <!--Licensed to the Apache Software Foundation (ASF) under oneor more contri ...

  5. 美团点评基于 Flink 的实时数仓建设实践

    https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651749037&idx=1&sn=4a448647b3dae5 ...

  6. 基于 Flink 的实时数仓生产实践

    数据仓库的建设是“数据智能”必不可少的一环,也是大规模数据应用中必然面临的挑战.在智能商业中,数据的结果代表了用户反馈.获取数据的及时性尤为重要.快速获取数据反馈能够帮助公司更快地做出决策,更好地进行 ...

  7. 基于 Kafka 的实时数仓在搜索的实践应用

    一.概述 Apache Kafka 发展至今,已经是一个很成熟的消息队列组件了,也是大数据生态圈中不可或缺的一员.Apache Kafka 社区非常的活跃,通过社区成员不断的贡献代码和迭代项目,使得 ...

  8. Clickhouse实时数仓建设

    1.概述 Clickhouse是一个开源的列式存储数据库,其主要场景用于在线分析处理查询(OLAP),能够使用SQL查询实时生成分析数据报告.今天,笔者就为大家介绍如何使用Clickhouse来构建实 ...

  9. 实时数仓(二):DWD层-数据处理

    目录 实时数仓(二):DWD层-数据处理 1.数据源 2.用户行为日志 2.1开发环境搭建 1)包结构 2)pom.xml 3)MykafkaUtil.java 4)log4j.properties ...

  10. 更强大的实时数仓构建能力!分析型数据库PostgreSQL 6.0新特性解读

    阿里云 AnalyticDB for PostgreSQL 为采用MPP架构的分布式集群数据库,完备支持SQL 2003,部分兼容Oracle语法,支持PL/SQL存储过程,触发器,支持标准数据库事务 ...

随机推荐

  1. Harris/Shi-Tomasi角点检测

    机器视觉--角点检测 什么是角点检测 在几何学里,我们会看到各种各样的三角形.多边形等,它们都有一个显著的特征:包含了角点信息.比如在三角形里,我们有三个角:在矩形里,我们有四个角.我们将找到这些图像 ...

  2. 【VR虚拟现实】-医疗行业的具体应用

    虚拟现实 (VR) 虽然经常与游戏联系在一起,但不可否认,未来科技少不了虚拟现实,其应用可以彻底改变许多行业.在医疗领域,无数人正在探索 VR 可以帮助患者和医疗从业者实现更好的治疗结果治疗方式,比如 ...

  3. Python 查找PDF中的指定文本并高亮显示

    在处理大量PDF文档时,有时我们需要快速找到特定的文本信息.本文将提供以下三个Python示例来帮助你在PDF文件中快速查找并高亮指定的文本. 查找并高亮PDF中所有的指定文本 查找并高亮PDF某个区 ...

  4. 记录--九个超级好用的 Javascript 技巧

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 在实际的开发工作过程中,积累了一些常见又超级好用的 Javascript 技巧和代码片段,包括整理的其他大神的 JS 使用技巧,今天 ...

  5. 这里有你不得不了解的Java 11版本特性说明

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  6. KingbaseES Insert On Conflict 功能

    针对数据写入时有主键冲突的情况,INSERT ON CONFLICT语法可以将冲突主键的INSERT行为转换为UPDATE行为,从而实现冲突主键的覆盖写入.该特性又称UPSERT覆盖写,与MySQL的 ...

  7. MySQL 索引失效场景总结

    查询条件有 or 假设在 customer_name 字段设置了普通索引,执行以下 sql: # type: ref, possible_keys: idx_customer_name, key: i ...

  8. 深入学习 XML 解析器及 DOM 操作技术

    所有主要的浏览器都内置了一个XML解析器,用于访问和操作XML XML 解析器 在访问XML文档之前,必须将其加载到XML DOM对象中 所有现代浏览器都有一个内置的XML解析器,可以将文本转换为XM ...

  9. 深入了解 Java 方法和参数的使用方法

    Java 方法 简介 方法是一块仅在调用时运行的代码.您可以将数据(称为参数)传递到方法中.方法用于执行特定的操作,它们也被称为函数. 使用方法的原因 重用代码:定义一次代码,多次使用. 提高代码的结 ...

  10. Matplotlib绘图设置--- 图例设置

    plt.legend()和ax.legend()参数设置 自动会将每条线的标签与其风格.颜色进行匹配. plt.legend(*args, **kwargs) Place a legend on th ...