数据库分库分表(sharding)系列转jimcsharp

图1.数据库分库分表(sharding)实施策略图解

1.准备阶段

对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系统业务逻辑和数据库schema.一个好的建议是绘制一张数据库ER图或领域模型图,以这类图为基础划分shard,直观易行,可以确保开发人员始终保持清醒思路。对于是选择数据库ER图还是领域模型图要根据项目自身情况进行选择。如果项目使用数据驱动的开发方式,团队以数据库ER图作为业务交流的基础,则自然会选择数据库ER图,如果项目使用的是领域驱动的开发方式,并通过OR-Mapping构建了一个良好的领域模型,那么领域模型图无疑是最好的选择。就我个人来说,更加倾向使用领域模型图,因为进行切分时更多的是以业务为依据进行分析判断,领域模型无疑更加清晰和直观。

2.分析阶段

1.垂直切分

垂直切分的依据原则是:将业务紧密,表间关联密切的表划分在一起,例如同一模块的表。结合已经准备好的数据库ER图或领域模型图,仿照活动图中的泳道概念,一个泳道代表一个shard,把所有表格划分到不同的泳道中。下面的分析示例会展示这种做法。当然,你也可以在打印出的ER图或模型图上直接用铅笔圈,一切取决于你自己的喜好。

2.水平切分

垂直切分后,需要对shard内表格的数据量和增速进一步分析,以确定是否需要进行水平切分。

2.1若划分到一起的表格数据增长缓慢,在产品上线后可遇见的足够长的时期内均可以由单一数据库承载,则不需要进行水平切分,所有表格驻留同一shard,所有表间关联关系会得到最大限度的保留,同时保证了书写SQL的自由度,不易受join、groupby、orderby等子句限制。

2.2若划分到一起的表格数据量巨大,增速迅猛,需要进一步进行水平分割。进一步的水平分割就这样进行:

2.2.1.结合业务逻辑和表间关系,将当前shard划分成多个更小的shard,通常情况下,这些更小的shard每一个都只包含一个主表(将以该表ID进行散列的表)和多个与其关联或间接关联的次表。这种一个shard一张主表多张次表的状况是水平切分的必然结果。这样切分下来,shard数量就会迅速增多。如果每一个shard代表一个独立的数据库,那么管理和维护数据库将会非常麻烦,而且这些小shard往往只有两三张表,为此而建立一个新库,利用率并不高,因此,在水平切分完成后可再进行一次“反向的Merge”,即:将业务上相近,并且具有相近数据增长速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据库上,在逻辑上它们依然是独立的shard,有各自的主表,并依据各自主表的ID进行散列,不同的只是它们的散列取模(即节点数量)必需是一致的。这样,每个数据库结点上的表格数量就相对平均了。

2.2.2.所有表格均划分到合适的shard之后,所有跨越shard的表间关联都必须打断,在书写sql时,跨shard的join、groupby、orderby都将被禁止,需要在应用程序层面协调解决这些问题。

特别想提一点:经水平切分后,shard的粒度往往要比只做垂直切割的粒度要小,原单一垂直shard会被细分为一到多个以一个主表为中心关联或间接关联多个次表的shard,此时的shard粒度与领域驱动设计中的“聚合”概念不谋而合,甚至可以说是完全一致,每个shard的主表正是一个聚合中的聚合根!

3.实施阶段

第二部分:示例演示

图2.jpetstore领域模型

由于系统较简单,我们很容易从模型上看出,其主要由三个模块组成:用户,产品和订单。那么垂直切分的方案也就出来了。接下来看水平切分,如果我们从一个实际的宠物店出发考虑,可能出现数据激增的单表应该是Account和Order,因此这两张表需要进行水平切分。对于Product模块来说,如果是一个实际的系统,Product和Item的数量都不会很大,因此只做垂直切分就足够了,也就是(Product,Category,Item,Iventory,Supplier)五张表在一个数据库结点上(没有水平切分,不会存在两个以上的数据库结点)。但是作为一个演示,我们假设产品模块也有大量的数据需要我们做水平切分,那么分析来看,这个模块要拆分出两个shard:一个是(Product(主),Category),另一个是(Item(主),Iventory,Supplier),同时,我们认为:这两个shard在数据增速上应该是相近的,且在业务上也很紧密,那么我们可以把这两个shard放在同一个数据库节点上,Item和Product数据在散列时取一样的模。根据前文介绍的图纸绘制方法,我们得到下面这张sharding示意图:

图3.jpetstoresharding示意图

对于这张图再说明几点:

1.使用泳道表示物理shard(一个数据库结点)

2.若垂直切分出的shard进行了进一步的水平切分,但公用一个物理shard的话,则用虚线框住,表示其在逻辑上是一个独立的shard。

3.深色实体表示主表

4.X表示需要打断的表间关联

(二)全局主键生成策略

第一部分:一些常见的主键生成策略

一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键生成机制。一方面,某个分区数据库自生成的ID无法保证在全局上是唯一的;另一方面,应用程序在插入数据之前需要先获得ID,以便进行SQL路由。目前几种可行的主键生成策略有:

1.UUID:使用UUID作主键是最简单的方案,但是缺点也是非常明显的。由于UUID非常的长,除占用大量存储空间外,最主要的问题是在索引上,在建立索引和基于索引进行查询时都存在性能问题。

2.结合数据库维护一个Sequence表:此方案的思路也很简单,在数据库中建立一个Sequence表,表的结构类似于:

[sql]viewplaincopy

01.CREATETABLE`SEQUENCE`(

02.`tablename`varchar(30)NOTNULL,

03.`nextid`bigint(20)NOTNULL,

04.PRIMARYKEY(`tablename`)

05.)ENGINE=InnoDB

每当需要为某个表的新纪录生成ID时就从Sequence表中取出对应表的nextid,并将nextid的值加1后更新到数据库中以备下次使用。此方案也较简单,但缺点同样明显:由于所有插入任何都需要访问该表,该表很容易成为系统性能瓶颈,同时它也存在单点问题,一旦该表数据库失效,整个应用程序将无法工作。有人提出使用Master-Slave进行主从同步,但这也只能解决单点问题,并不能解决读写比为1:1的访问压力问题。

除此之外,还有一些方案,像对每个数据库结点分区段划分ID,以及网上的一些ID生成算法,因为缺少可操作性和实践检验,本文并不推荐。实际上,接下来,我们要介绍的是Fickr使用的一种主键生成方案,这个方案是目前我所知道的最优秀的一个方案,并且经受了实践的检验,可以为大多数应用系统所借鉴。

第二部分:一种极为优秀的主键生成策略

flickr开发团队在2010年撰文介绍了flickr使用的一种主键生成测策略,同时表示该方案在flickr上的实际运行效果也非常令人满意,原文连接:TicketServers:DistributedUniquePrimaryKeysontheCheap这个方案是我目前知道的最好的方案,它与一般Sequence表方案有些类似,但却很好地解决了性能瓶颈和单点问题,是一种非常可靠而高效的全局主键生成方案。

图1.flickr采用的sharding主键生成方案示意图

flickr这一方案的整体思想是:建立两台以上的数据库ID生成服务器,每个服务器都有一张记录各表当前ID的Sequence表,但是Sequence中ID增长的步长是服务器的数量,起始值依次错开,这样相当于把ID的生成散列到了每个服务器节点上。例如:如果我们设置两台数据库ID生成服务器,那么就让一台的Sequence表的ID起始值为1,每次增长步长为2,另一台的Sequence表的ID起始值为2,每次增长步长也为2,那么结果就是奇数的ID都将从第一台服务器上生成,偶数的ID都从第二台服务器上生成,这样就将生成ID的压力均匀分散到两台服务器上,同时配合应用程序的控制,当一个服务器失效后,系统能自动切换到另一个服务器上获取ID,从而保证了系统的容错。

关于这个方案,有几点细节这里再说明一下:

实现该方案,应用程序同样需要做一些处理,主要是两方面的工作:

1.自动均衡数据库ID生成服务器的访问

2.确保在某个数据库ID生成服务器失效的情况下,能将请求转发到其他服务器上执行。

(三)关于使用框架还是自主开发以及sharding实现层面的考量

一、sharding逻辑的实现层面

从一个系统的程序架构层面来看,sharding逻辑可以在DAO层、JDBCAPI层、介于DAO与JDBC之间的Spring数据访问封装层(各种spring的template)以及介于应用服务器与数据库之间的sharding代理服务器四个层面上实现。

在DAO层实现

当团队决定自行实现sharding的时候,DAO层可能是嵌入sharding逻辑的首选位置,因为在这个层面上,每一个DAO的方法都明确地知道需要访问的数据表以及查询参数,借助这些信息可以直接定位到目标shard上,而不必像框架那样需要对SQL进行解析然后再依据配置的规则进行路由。另一个优势是不会受ORM框架的制约。由于现在的大多数应用在数据访问层上会依赖某种ORM框架,而多数的shrading框架往往无法支持或只能支持一种orm框架,这使得在选择和应用框架时受到了很大的制约,而自行实现sharding完全没有这方面的问题,甚至不同的shard使用不同的orm框架都可以在一起协调工作。比如现在的java应用大多使用hibernate,但是当下还没有非常令人满意的基于hibernate的sharding框架,(关于hibernatehards会在下文介绍),因此很多团队会选择自行实现sharding。

简单总结一下,在DAO层自行实现sharding的优势在于:不受ORM框架的制约、实现起来较为简单、易于根据系统特点进行灵活的定制、无需SQL解析和路由规则匹配,性能上表现会稍好一些;劣势在于:有一定的技术门槛,工作量比依靠框架实现要大(反过来看,框架会有学习成本)、不通用,只能在特定系统里工作。当然,在DAO层同样可以通过XML配置或是注解将sharding逻辑抽离到“外部”,形成一套通用的框架.不过目前还没有出现此类的框架。

在ORM框架层实现

在JDBCAPI层实现

JDBCAPI层是很多人都会想到的一个实现sharding的绝佳场所,如果我们能提供一个实现了sharding逻辑的JDBCAPI实现,那么sharding对于整个应用程序来说就是完全透明的,而这样的实现可以直接作为通用的sharding产品了。但是这种方案的技术门槛和工作量显然不是一般团队能做得来的,因此基本上没有团队会在这一层面上实现sharding,甚至也没有此类的开源产品。笔者知道的只有一款商业产品dbShards采用的是这一方案。

在介于DAO与JDBC之间的Spring数据访问封装层实现

在springd大行其道的今天,几乎没有哪个java平台上构建的应用不使用spring,在DAO与JDBC之间,spring提供了各种template来管理资源的创建与释放以及与事务的同步,大多数基于spring的应用都会使用template类做为数据访问的入口,这给了我们另一个嵌入sharding逻辑的机会,就是通过提供一个嵌入了sharding逻辑的template类来完成sharding工作.这一方案在效果上与基于JDBCAPI实现的方案基本一致,同样是对上层代码透明,在进行sharding改造时可以平滑地过度,但它的实现却比基于JDBCAPI的方式简单,因此成为了不少框架的选择,阿里集团研究院开源的CobarClient就是这类方案的一种实现。

在应用服务器与数据库之间通过代理实现

在应用服务器与数据库之间加入一个代理,应用程序向数据发出的数据请求会先通过代理,代理会根据配置的路由规则,对SQL进行解析后路由到目标shard,因为这种方案对应用程序完全透明,通用性好,所以成为了很多sharding产品的选择。在这方面较为知名的产品是mysql官方的代理工具:MysqlProxy和一款国人开发的产品:amoeba。mysqlproxy本身并没有实现任何sharding逻辑,它只是作为一种面向mysql数据库的代理,给开发人员提供了一个嵌入sharding逻辑的场所,它使用lua作为编程语言,这对很多团队来说是需要考虑的一个问题。amoeba则是专门实现读写分离与sharding的代理产品,它使用非常简单,不使用任何编程语言,只需要通过xml进行配置。不过amoeba不支持事务(从应用程序发出的包含事务信息的请求到达amoeba时,事务信息会被抹去,因此,即使是单点数据访问也不会有事务存在)一直是个硬伤。当然,这要看产品的定位和设计理念,我们只能说对于那些对事务要求非常高的系统,amoeba是不适合的。

二、使用框架还是自主开发?

前面的讨论中已经罗列了很多开源框架与产品,这里再整理一下:基于代理方式的有MySQLProxy和Amoeba,基于Hibernate框架的是HibernateShards,通过重写spring的ibatistemplate类是CobarClient,这些框架各有各的优势与短板,架构师可以在深入调研之后结合项目的实际情况进行选择,但是总的来说,我个人对于框架的选择是持谨慎态度的。一方面多数框架缺乏成功案例的验证,其成熟性与稳定性值得怀疑。另一方面,一些从成功商业产品开源出框架(如阿里和淘宝的一些开源项目)是否适合你的项目是需要架构师深入调研分析的。当然,最终的选择一定是基于项目特点、团队状况、技术门槛和学习成本等综合因素考量确定的。

(四)多数据源的事务处理

分布式事务

这是最为人们所熟知的多数据源事务处理机制。本文并不打算对分布式事务做过多介绍,读者可参考此文:关于分布式事务、两阶段提交、一阶段提交、BestEfforts1PC模式和事务补偿机制的研究。在这里只想对分布式事务的利弊作一下分析。

优势:

1.基于两阶段提交,最大限度地保证了跨数据库操作的“原子性”,是分布式系统下最严格的事务实现方式。

2.实现简单,工作量小。由于多数应用服务器以及一些独立的分布式事务协调器做了大量的封装工作,使得项目中引入分布式事务的难度和工作量基本上可以忽略不计。

劣势:

基于BestEfforts1PC模式的事务

与分布式事务采用的两阶段提交不同,BestEfforts1PC模式采用的是一阶段端提交,牺牲了事务在某些特殊情况(当机、网络中断等)下的安全性,却获得了良好的性能,特别是消除了对水平伸缩的桎酷。DistributedtransactionsinSpring,withandwithoutXA一文对BestEfforts1PC模式进行了详细的说明,该文提供的Demo代码更是直接给出了在Spring环境下实现一阶段提交的多数据源事务管理示例。不过需要注意的是,原示例是基于spring3.0之前的版本,如果你使用spring3.0+,会得到如下错误:java.lang.IllegalStateException:Cannotactivatetransactionsynchronization-alreadyactive,如果使用spring3.0+,你需要参考spring-data-neo4j的实现。鉴于BestEfforts1PC模式的性能优势,以及相对简单的实现方式,它被大多数的sharding框架和项目采用。

事务补偿机制

小结

分布式事务,最严格的事务实现,但性能是个大问题;BestEfforts1PC模式,性能与事务可靠性的平衡,支持系统水平伸缩,大多数情况下是最合适的选择;事务补偿机制,只能适用于对事务性要求不高,允许数据“最终一致”即可的系统,牺牲实时一致性,获得最大的性能回报。

(五)一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案

本文将重点围绕“数据库扩容”进行深入讨论,并提出一种允许自由规划并能避免数据迁移和修改路由代码的Sharding扩容方案

Sharding扩容——系统维护不能承受之重

一般来说,“理想”的扩容方案应该努力满足以下几个要求:

目前,能够避免数据迁移的优秀方案并不多,相对可行的有两种,一种是维护一张记录数据ID和目标Shard对应关系的映射表,写入时,数据都写入新扩容的Shard,同时将ID和目标节点写入映射表,读取时,先查映射表,找到目标Shard后再执行查询。该方案简单有效,但是读写数据都需要访问两次数据库,且映射表本身也极易成为性能瓶颈。为此系统不得不引入分布式缓存来缓存映射表数据,但是这样也无法避免在写入时访问两次数据库,同时大量映射数据对缓存资源的消耗以及专门为此而引入分布式缓存的代价都是需要权衡的问题。另一种方案来自淘宝综合业务平台团队,它利用对2的倍数取余具有向前兼容的特性(如对4取余得1的数对2取余也是1)来分配数据,避免了行级别的数据迁移,但是依然需要进行表级别的迁移,同时对扩容规模和分表数量都有限制。总得来说,这些方案都不是十分的理想,多多少少都存在一些缺点,这也从一个侧面反映出了Sharding扩容的难度。

取长补短,兼容并包——一种理想的Sharding扩容方案

原理

图1.Sharding拓扑结构领域模型

在这个模型中,有几个细节需要注意:ShardGroup的writable属性用于标识该ShardGroup是否可以写入数据,一个Partition在任何时候只能有一个ShardGroup是可写的,这个ShardGroup往往是最近一次扩容引入的;startId和endId属性用于标识该ShardGroup的ID增量区间;Shard的hashValue属性用于标识该Shard节点接受哪些散列值的数据;FragmentTable的startId和endId是用于标识该分段表储存数据的ID区间。

示例

让我们通过示例来了解这套方案是如何工作的。

阶段一:初始上线

假设某系统初始上线,规划为某表提供4000W条记录的存储能力,若单表存储上限为1000W条,单库存储上限为2000W条,共需2个Shard,每个Shard包含两个分段表,ShardGroup增量区间为0-4000W,按2取余分散到2个Shard上,具体规划方案如下:

图2.初始4000W存储规模的规划方案

与之相适应,Sharding拓扑结构的元数据如下:

图3.对应Sharding元数据

阶段二:系统扩容

图4.二次扩容6000W存储规模的规划方案

相应拓扑结构表数据下:

图5.对应Sharding元数据

从这个扩容案例中我们可以看出该方案允许根据硬件情况进行灵活规划,对扩容规模和节点数量没有硬性规定,是一种非常自由的扩容方案。

增强

图6.增强后的Sharding拓扑结构领域模型

让我们还是通过一个示例来了解升级后的方案是如何工作的。

阶段三:不扩容,重复利用再生存储空间

图7.重复利用2000W再生存储空间的规划方案

相应拓扑结构的元数据如下:

图8.对应Sharding元数据

这套方案综合利用了增量区间和散列两种路由方式的优势,避免了数据迁移和“热点”问题,同时,它对Sharding拓扑结构建模,使用了一致的路由算法,从而避免了扩容时修改路由代码,是一种理想的Sharding扩容方案。

THE END
1.[发现报告]:天元宠物机构调研纪要天元宠物机构调研报告 调研日期:2024-11-07 杭州天元宠物用品股份有限公司成立于2003年,总部位于杭州,是一家专注于宠物用品的设计开发、生产、销售的综合性企业,产品包括宠物窝垫、猫爬架、宠物玩具、宠物服饰、电子智能宠物用品以及宠物食品等多系列、全品类宠物产品。天元宠物注重宠物产业,以“让宠爱,更健康”为使命...https://www.fxbaogao.com/detail/4582685
2.第十三届中国国际空间设计大赛名单行业要闻中装新网第十三届中国国际空间设计大赛自2022年11月启动以来,通过线上和线下的作品征集形式,共征集作品9137项,经过初评、复评、终评及终审,最终获奖名单如下。 第十三届中国国际空间设计大赛获奖名单 奖项 证书编号 设计作品 设计单位 设计师 1、酒店空间方案类 金奖 2023JDFA05401 重庆金隅大成时代都汇A08-3酒店地块精装修...http://www.cbda.cn/html/yj/20230921/138774.html
3.GaceDesign少儿空间设计的微博GaceDesign少儿空间设计 6月19日 11:46 来自微博视频号 “Paw Day宠物旗舰店”,由罕创设计。这是一家由中国宠物营养先驱企业佩蒂为爱宠人士建立的多功能社交中心。旗舰店外观采用简约精致的黑色和奶油色,主入口和面向室外的大折叠窗设计十分显眼。入口前方设有大片户外犬类游乐区,为不同体型的狗狗提供活动空间。https://weibo.com/gacedesign
1.宠物医院设计戈者设计53 ㎡ 打造木质结构多功能宠物店设计 Aug 30 , 2023 | Views : 501 A+ 宠物诊所设计在 53 ㎡ 的空间内体现了非典型宠物空间设计的价值,为项目提供了实用的家具。如何为宠物提供一个宽敞的娱乐场所是一个严峻的挑战,即使 5 间诊室也是医院运营所必需的。最主要的问题是 ... Read more Category : 室内...https://www.gavindesign.com/tag/chongwuyiyuansheji/
2.隐藏小巷的特色宠物店,你好,这里是停狗位信息传输摘要:你好,这是一家隐藏在小巷中的特色宠物店——“停狗位”。该店提供宠物日常护理、宠物用品销售以及宠物娱乐等服务。店内环境温馨舒适,专业的工作人员为宠物爱好者提供全方位的宠物体验。这里不仅是宠物的休憩之地,也是宠物爱...http://www.rhythmall.cn/post/9982.html
3.基于共生理念的人宠社交空间设计研究本课题基于共生理念为研究背景对人宠社交空间进行设计实践。首先,以宠物猫为例,从宠物与人共同的角度出发调查了解宠物猫的心理及行为特征,综合宠物与人两者之间的情感和心理需求,提出健康的人宠关系;通过调研当前宠物行业的发展与变化,总结出国内人宠社交空间的不足之处;再者,以共生理念原则分析宠物猫、人、环境三者...https://cdmd.cnki.com.cn/Article/CDMD-10255-1021654224.htm
4.MINGSDESIGN上海咖啡馆设计,商业空间设计,私宅设计,餐厅设计...MINGS DESIGN,森治空间设计,咖啡馆设计,咖啡店设计,咖啡厅设计,西餐店设计,餐饮设计,餐厅设计,上海咖啡馆设计,上海咖啡店设计,上海咖啡厅设计,上海咖啡馆装修,咖啡馆策划,上海商业空间设计,上海私宅设计,上海酒吧设计,上海店面设计,上海餐饮设计,上海餐厅设计,上海办公室设http://www.mingsdesign.cn/
5.2022AR文旅元宇宙AR+文旅文旅消费新嘲Online第3页回归日常生活场景,以民生视角思考旅游,是理论研究者、产业实践者和政策制定者应该坚持也必须坚持的立场、观点和方法。随着游客广泛进入目的地居民的日常生活空间,旅游景区乃至旅游产业的边界正处于消失和重构的进程中,由需求侧来定义旅游景区将成为不可逆的趋势。为适应新发展阶段的变化,旅游景区要更加强调游客视角,目的地...https://www.zhihuilvyou.com/?m=2022&paged=3&=1
6.创新创业实践2.2.2 构建较完善可行的《拼布艺术》创新创业教育教学方案设计,为艺术设计类及其他专业的课程教学进行创新创业教育探索提供有价值的借鉴和参考。利用以“创新”为核心的艺术设计专业,激发学生的活跃思维,培养学生的独立思考、创新设计能力与和实践动手能力,提升学生的专业创新意识与创业能力。 https://www.360wenmi.com/f/filee6ql56n0.html
7.springboot宠物相亲平台计算机设计毕业源码16285本文针对现代社会中宠物相亲需求日益增长的背景下,设计并实现了一款基于Spring Boot框架的宠物相亲平台。该平台结合了互联网科技和宠物交友需求,为宠物主人提供了一个便捷且安全的交友平台。 本设计采用了前后端分离的架构,前端利用HTML、CSS和JavaScript进行开发,实现了萌宠朋友圈、公告、知识科普、人类发言区、萌宠相亲...https://blog.csdn.net/Weixin_CXSJ881/article/details/143446382
8.软件工程专业毕业设计十篇在应用型本科院校中,尤其是软件工程专业,毕业设计作为教学计划的重要组成部分,是实践教学中的最后一个环节,也是对学生在校期间所学知识的一次综合、全面的总结、应用和提高[1]。由于毕业生数量的不断增加和软件行业的迅猛发展,导致就业门槛越来越高,就业压力也越来越大,通过毕业设计过程中的训练,能有效提高学生的工程...https://www.mingkanw.com/w/keyidq4whyoi.html
9.特粗狗笼子小型犬中型犬加粗加固大型犬狗笼室内家用宠物店专用笼...1.京东价:京东价为商品的销售价,是您最终决定是否购买商品的依据。 2.划线价:商品展示的划横线价格为参考价,该价格可能是品牌专柜标价、商品吊牌价或由品牌供应商提供的正品零售价(如厂商指导价、建议零售价等)或该商品在京东平台上曾经展示过的销售价;由于地区、时间的差异性和市场行情波动,品牌专柜标价、商品吊牌...http://item.m.jd.com/product/10121887958561.html
10.动物医学个人职业规划书(通用6篇)我所所学的专业为动物医学,我们学习动物解剖学、动物病理学、动物生理学等方面,可以更加深入对动物的研究学习,为我们以后做一名合格的兽医打下坚实的基础。动物医学专业培养具备解剖、预防、治疗等方面的基础理论知识,熟悉动物的病理,掌握基本的兽医技能,具有分析和解决动物病理实际问题的科学研究和实际工作能力,能在企业...https://www.ruiwen.com/zhiyeguihua/6666603.html
11.今日蚂蚁新村答案蚂蚁新村形堂答案最新简单来说,植物设计就是用植物造景,是园林景观设计和室内软装设计的结合。设计师根据不同的客户需求,将各种各样的植物组合搭配,从而实现植物与空间的完美融合。此外,植物养护也是植物设计师的工作内容。 11.5 我国哪座城市被誉为“中国古戏台之乡“?江西乐平 ...https://app.ali213.net/gl/713489.html
12.小学英语说课稿(常用15篇)教材强调学生在学习过程中的感悟、体验、实践、参与以及思维能力的发展,在良好的语言环境中,融学习情感、学习能力的形成与语言学习的全过程中,突出兴趣培养,重视学科内容的有效融合,注重培养学生自主学习的意识和能力。处理教材时,我把新授内容分两课时进行,在第一课时我已教了四个运动项目的单词和like+v-ing形式的...https://www.qunzou.com/jiaoxue/shuokegao/1844687.html