精华内容
下载资源
问答
  • 前言 移动互联网时代,海量的用户数据每天都产生,...mysql中,每个数据库最多可创建20亿个表,一个表允许定义1024列,每行的最大长度为8092字节(不包括copy文本和图像类型的长度)。当表中定义有varchar、n...

    前言
    移动互联网时代,海量的用户数据每天都在产生,基于用户使用数据等这样的分析,都需要依靠数据统计和分析,当数据量小时,数据库方面的优化显得不太重要,一旦数据量越来越大,系统响应会变慢,TPS直线下降,直至服务不可用。
    在这里插入图片描述

    补充
    在mysql中,每个数据库最多可创建20亿个表,一个表允许定义1024列,每行的最大长度为8092字节(不包括copy文本和图像类型的长度)。当表中定义有varchar、nvarchar或varbinary类型列时,如果向表中插入的数据行超过8092字节时将导致Transact-SQL语句失败,并产生错误信息。SQL Server对每个表中行的数量没有直接限制,但它受数据库存储空间的限制。每个数据库的最大空间1048516TB,所以一个表可用的最大空间为1048516TB减去数据库类系zhidao统表和其它数据库对象所占用的空间。

    这里还要注意:突破高薪Java架构项目经验永远是核心,如果你没有最新JAVA架构实战教程及大厂30k+面试宝典,可以去小编的Java架构学习.裙 :七吧伞吧零而衣零伞 (数字的谐音)转换下可以找到了,里面很多新JAVA架构项目教程,还可以跟老司机交流讨教!

    问题
    可能有人会问,为何不用Oracle呢?确实,很多开发者写代码时并不会关心SQL的问题,凡是性能问题都交给DBA负责SQL优化,可是,不是每一个项目都会有DBA,也不是所有的项目都会采用Oracle数据库,而且,Oracle数据库在大数据量的背景下,解决性能问题,也不见的是一个非常轻松的事情。

    那么,MySQL能不能支撑亿级的数据量呢,我的答案是肯定的,绝大部分的互联网公司,它们采用的数据存储方案,绝大部分都是以MySQL为主,不差钱的国企和银行,以Oracle为主,而且有专职的DBA为你服务。

    本文会以一个实际的项目应用为例,层层向大家剖析[如何进行数据库的优化]项目背景是企业级的统一消息处理平台,客户数据在5千万加,每分钟处理消息流水1千万,每天消息流水1亿左右。

    虽说MySQL单表可以存储10亿级的数据,但这个时候性能非常差。既然一张表无法搞定,那么就想办法将数据放到多个地方来解决问题吧,于是,数据库分库分表的方案便产生了,目前比较普遍的方案有三个:分区、分库分表、NoSQL/NewSQL。

    在实际的项目中,往往是这三种方案的结合来解决问题,目前绝大部分系统的核心数据都是以RDBMS存储为主,NoSQL/NewSQL存储为辅。

    分区
    分区方案

    分区表是由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们也可以直接访问各个分区,存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个相同的索引,从存储引擎的角度来看,底层表和一个普通表没有任何不同,存储引擎也无须知道这是一个普通表还是一个分区表的一部分。这个方案也不错,它对用户屏蔽了sharding的细节,即使查询条件没有sharding column,它也能正常工作(只是这时候性能一般)。不过它的缺点很明显:很多的资源都受到单机的限制,例如连接数,网络吞吐等。如何进行分区,在实际应用中是一个非常关键的要素之一。在我们的项目中,以客户信息为例,客户数据量5000万加,项目背景要求保存客户的银行卡绑定关系,客户的证件绑定关系,以及客户绑定的业务信息。此业务背景下,该如何设计数据库呢。项目一期的时候,我们建立了一张客户业务绑定关系表,里面冗余了每一位客户绑定的业务信息。基本结构大致如下:

    image

    查询时,对银行卡做索引,业务编号做索引,证件号做索引。随着需求大增多,这张表的索引会达到10个以上。而且客户解约再签约,里面会保存两条数据,只是绑定的状态不同。假设我们有5千万的客户,5个业务类型,每位客户平均2张卡,那么这张表的数据量将会达到惊人的5亿,事实上我们系统用户量还没有过百万时就已经不行了。MySQL数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看), 一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放表数据的,一个是myi存表索引的。这三个文件都非常的庞大,尤其是.myd文件,快5个G了。下面进行第一次分区优化,MySQL支持的分区方式有四种:

    image

    在我们的项目中,range分区和list分区没有使用场景,如果基于绑定编号做range或者list分区,绑定编号没有实际的业务含义,无法通过它进行查询,因此,我们就剩下 HASH 分区和 KEY 分区了, HASH 分区仅支持int类型列的分区,且是其中的一列。看看我们的库表结构,发现没有哪一列是int类型的,如何做分区呢?可以增加一列,绑定时间列,将此列设置为int类型,然后按照绑定时间进行分区,将每一天绑定的用户分到同一个区里面去。这次优化之后,我们的插入快了许多,但是查询依然很慢,为什么,因为在做查询的时候,我们也只是根据银行卡或者证件号进行查询,并没有根据时间查询,相当于每次查询,MySQL都会将所有的分区表查询一遍。

    然后进行第二次方案优化,既然hash分区和key分区要求其中的一列必须是int类型的,那么创造出一个int类型的列出来分区是否可以。分析发现,银行卡的那串数字有秘密。银行卡一般是16位到19位不等的数字串,我们取其中的某一位拿出来作为表分区是否可行呢,通过分析发现,在这串数字中,其中确实有一位是0到9随机生成的,不同的卡串长度,这一位不同,绝不是最后一位,最后位数字一般都是校验位,不具有随机性。我们新设计的方案,基于银行卡号+随机位进行KEY分区,每次查询的时候,通过计算截取出这位随机位数字,再加上卡号,联合查询,达到了分区查询的目的,需要说明的是,分区后,建立的索引,也必须是分区列,否则的话,MySQL还是会在所有的分区表中查询数据。那么通过银行卡号查询绑定关系的问题解决了,那么证件号呢,如何通过证件号来查询绑定关系。前面已经讲过,做索引一定是要在分区健上进行,否则会引起全表扫描。

    我们再创建了一张新表,保存客户的证件号绑定关系,每位客户的证件号都是唯一的,新的证件号绑定关系表里,证件号作为了主键,那么如何来计算这个分区健呢,客户的证件信息比较庞杂,有身份证号,港澳台通行证,机动车驾驶证等等,如何在无序的证件号里找到分区健。

    为了解决这个问题,我们将证件号绑定关系表一分为二,其中的一张表专用于保存身份证类型的证件号,另一张表则保存其他证件类型的证件号,在身份证类型的证件绑定关系表中,我们将身份证号中的月数拆分出来作为了分区健,将同一个月出生的客户证件号保存在同一个区,这样分成了12个区,其他证件类型的证件号,数据量不超过10万,就没有必要进行分区了。这样每次查询时,首先通过证件类型确定要去查询哪张表,再计算分区健进行查询。

    作了分区设计之后,保存2000万用户数据的时候,银行卡表的数据保存文件就分成了10个小文件,证件表的数据保存文件分成了12个小文件,解决了这两个查询的问题,还剩下一个问题就是,业务编号呢,怎么办,一个客户有多个签约业务,如何进行保存,这时候,采用分区的方案就不太合适了,它需要用到分表的方案。

    分库分表
    如何进行分库分表,目前互联网上有许多的版本,比较知名的一些方案:

    阿里的TDDL,DRDS和cobar,

    京东金融的sharding-jdbc;

    间组织的MyCAT;

    360的Atlas;

    美团的zebra;

    其他比如网易、58、京东等公司都有自研的中间件。

    但是这么多的分库分表中间件方案,归总起来,就两类:client模式和proxy模式。

    image

    client模式

    image

    proxy模式

    无论是client模式,还是proxy模式,几个核心的步骤是一样的:SQL解析,重写,路由,执行,结果归并。个人比较倾向于采用client模式,它架构简单,性能损耗也比较小,运维成本低。如果在项目中引入mycat或者cobar,他们的单机模式无法保证可靠性,一旦宕机则服务就变得不可用,你又不得不引入HAProxy来实现它的高可用集群部署方案, 为了解决HAProxy的高可用问题,又需要采用Keepalived来实现。

    image

    我们在项目中放弃了这个方案,采用了shardingjdbc的方式。回到刚才的业务问题,如何对业务类型进行分库分表。分库分表第一步也是最重要的一步,即sharding column的选取,sharding column选择的好坏将直接决定整个分库分表方案最终是否成功。

    而sharding column的选取跟业务强相关。在我们的项目场景中,sharding column无疑最好的选择是业务编号。通过业务编号,将客户不同的绑定签约业务保存到不同的表里面去,查询时,根据业务编号路由到相应的表中进行查询,达到进一步优化SQL的目的。

    前面我们讲到了基于客户签约绑定业务场景的数据库优化,下面我们再聊一聊,对于海量数据的保存方案。

    垂直分库
    对于每分钟要处理近1000万的流水,每天流水近1亿的量,如何高效的写入和查询,是一项比较大的挑战。还是老办法,分库分表分区,读写分离,只不过这一次,我们先分表,再分库,最后分区。

    我们将消息流水按照不同的业务类型进行分表,相同业务的消息流水进入同一张表,分表完成之后,再进行分库。我们将流水相关的数据单独保存到一个库里面去,这些数据,写入要求高,查询和更新到要求低,将它们和那些更新频繁的数据区分开。分库之后,再进行分区。

    image

    这是基于业务垂直度进行的分库操作,垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库,以达到系统资源的饱和利用率。这样的分库方案结合应用的微服务治理,每个微服务系统使用独立的一个数据库。将不同模块的数据分库存储,模块间不能进行相互关联查询,如果有,要么通过数据冗余解决,要么通过应用代码进行二次加工进行解决。

    若不能杜绝跨库关联查询,则将小表到数据冗余到大数据量大库里去。假如,流水大表中查询需要关联获得渠道信息,渠道信息在基础管理库里面,那么,要么在查询时,代码里二次查询基础管理库中的渠道信息表,要么将渠道信息表冗余到流水大表中。

    将每天过亿的流水数据分离出去之后,流水库中单表的数据量还是太庞大,我们将单张流水表继续分区,按照一定的业务规则,(一般是查询索引列)将单表进行分区,一个表编程N个表,当然这些变化对应用层是无法感知的。

    image

    分区表的设置,一般是以查询索引列进行分区,例如,对于流水表A,查询需要根据手机号和批次号进行查询,所以我们在创建分区的时候,就选择以手机号和批次号进行分区,这样设置后,查询都会走索引,每次查询MySQL都会根据查询条件计算出来,数据会落在那个分区里面,直接到对应的分区表中检索即可,避免了全表扫描。

    对于每天流水过亿的数据,当然是要做历史表进行数据迁移的工作了。客户要求流水数据需要保存半年的时间,有的关键流水需要保存一年。删数据是不可能的了,也跑不了路,虽然当时非常有想删数据跑路的冲动。其实即时是删数据也是不太可能的了,delete的拙劣表演先淘汰了,truncate也快不了多少,我们采用了一种比较巧妙方法,具体步骤如下:

    创建一个原表一模一样的临时表1 create table test_a_serial_1 like test_a_serial;

    将原表命名为临时表2 alter table test_a_serial rename test_a_serial_{date};

    将临时表1改为原表 alter table able test_a_serial_1 rename able test_a_serial; 此时,当日流水表就是一张新的空表了,继续保存当日的流水,而临时表2则保存的是昨天的数据和部分今天的数据,临时表2到名字中的date时间是通过计算获得的昨日的日期;每天会产生一张带有昨日日期的临时表2,每个表内的数据大约是有1000万。

    将当日表中的历史数据迁移到昨日流水表中去 这样的操作都是用的定时任务进行处理,定时任务触发一般会选择凌晨12点以后,这个操作即时是几秒内完成,也有可能会有几条数据落入到当日表中去。因此我们最后还需要将当日表内的历史流水数据插入到昨日表内;insert into test_a_serial_{date}(cloumn1,cloumn2….) select(cloumn1,cloumn2….) from test_a_serial where LEFT(create_time,8) > CONCAT(date); commit;

    如此,便完成了流水数据的迁移;

    根据业务需要,有些业务数据需要保存半年,超过半年的进行删除,在进行删除的时候,就可以根据表名中的_{date}筛选出大于半年的流水直接删表;

    半年的时间,对于一个业务流水表大约就会有180多张表,每张表又有20个分区表,那么如何进行查询呢?由于我们的项目对于流水的查询实时性要求不是特别高,因此我们在做查询时,进行了根据查询时间区间段进行路由查询的做法。

    大致做法时,根据客户选择的时间区间段,带上查询条件,分别去时间区间段内的每一张表内查询,将查询结果保存到一张临时表内,然后,再去查询临时表获得最终的查询结果。

    以上便是我们面对大数据量的场景下,数据库层面做的相应的优化,一张每天一亿的表,经过拆分后,每个表分区内的数据在500万左右。这样设计之后,我们还面临了一些其他问题,例如流水的统计问题,这么大量的数据,项目中的统计维度达到100多种,哪怕是每天count100次,也是及其困难多,我们采用了实时计算统计的方式来解决了这个问题,相关的技术涉及到实时计算,消息队列,缓存中间件等内容,尽请期待吧!

    最后注意:突破高薪Java架构项目经验永远是核心,如果你没有最新JAVA架构实战教程及大厂30k+面试宝典,可以去小编的Java架构学习.裙 :七吧伞吧零而衣零伞 (数字的谐音)转换下可以找到了,里面很多新JAVA架构项目教程,还可以跟老司机交流讨教!

    本文的文字及图片来源于网络加上自己的想法,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理

    展开全文
  • 如何在微服务架构下进行数据设计? 微服务是一个软件架构模式,对微服务的讨论大多集中容器或其他技术是否能很好的实施微服务这些方面。 本文将从以下几个角度来和大家分享微服务架构下进行数据设计需要关注的...

    如何在微服务架构下进行数据设计?

    微服务是一个软件架构模式,对微服务的讨论大多集中在容器或其他技术是否能很好的实施微服务这些方面。

    本文将从以下几个角度来和大家分享在微服务架构下进行数据设计需要关注的地方,旨在帮助大家在构建微服务架构时,提供一个数据方面的视角:

    什么是微服务

    微服务的优势及架构特点

    微服务架构下的数据设计

    一个适合微服务架构的数据库

    1 什么是微服务

    按照 Martin Fowler 的定义,微服务是一个软件架构模式,通过开发一系列的小型服务的方式来实现一个应用。每一个这样的小服务通常都是运行在自己的进程里面,并且通过轻量级的HTTP API 方式进行通讯。

    这些服务通常会以业务模块为界限,能够被单独开发部署,往往都会用自动化的部署工具来进行产品的发布。通过使用微服务方法,大公司可以更快推出新产品和服务,使得开发团队与业务目标保持一致。

    2 微服务的优势

    微服务方法体现出许多优势,包括更快的上线时间、灵活性、弹性、一致性以及相对更低的成本。

    更快的上线时间

    实施微服务架构可以使组织更快地将应用程序推向市场。对整体应用程序的更改(即使很小)需要重新部署整个应用程序堆栈,从而引入风险和复杂性。

    相反,服务的更新可以立即提交、测试和部署,对个别服务的更改不会影响系统的其他部分。

    更好的灵活性和可扩展性

    微服务方法在扩展应用程序时也提供了灵活性。单片应用程序要求整个系统(及其所有功能)同时扩展。

    使用微服务,只需要缩放需要额外性能的组件或功能。可以通过部署更多微服务实例来扩展服务范围,从而实现更有效的容量规划并降低软件许可成本,从而降低总体拥有成本。

    弹性

    使用单体应用程序时,组件的故障可能会危及整个应用程序。在微服务中,每项服务都是隔离的,以防止级联失败导致整个系统崩溃。如果单个微服务的所有实例均失败,则整体服务可能会降级,但其他组件仍可提供有价值的服务。

    更容易的规模化

    微服务使技术团队能够与组织需求保持一致,并且可以调整团队的大小以匹配所需的任务。通常,微服务团队规模较小,但是跨部门(如一般涵盖Ops、Dev、QA),并专注于整个应用程序的单个组件。

    通过提供对个人服务的所有权,而不是功能区域,微服务还可以打破团队之间的孤岛,并改善协作。这种方法对于分布式和远程团队尤其强大。例如,不同地点的团队可以独立发布和部署功能。

    3 微服务的技术特点

    让我们通过一个例子来了解微服务架构的技术特点。联邦银行的架构师 Jonnathan 非常不喜欢他的产品经理 Mandy,因为他觉得 Mandy 永远有无穷无尽的想法要实现,搞得他成天就在不断地修改代码。

    但是 Mandy 是老板的红人,而且用户对产品的反响也不错,所以很多时候他只能默默的服从。这一天 Mandy 又成功的说服了老板要在他们的客户体验提升项目中增加舆情分析和 AI 客户服务模块,希望通过对社交媒体上有关联邦银行的所有评论进行实时的监控和分析来及时发现联邦银行的产品反馈或者用户体验问题。

    Jonnathan已经预感到了这样前所未有的应用场景,会有太多的未知和太多的改变,于是这次决定尝试使用 Microservices 来构建这个应用。这个是 Jonnathan 设计的架构,系统要求对客户的社交账号,如Facebook、Twitter、Google+ 及 Snapchat 公开的信息及评论进行收集,并在某些合适的时候使用 AI 技术直接和用户通过社交工具进行互动。

    在这里插入图片描述

    在上图这个架构里面,Jonnathan 把4个不同社交媒体的数据采集和交互用 4 个独立的模块进行实现。并用一个 Feed Merge 服务,一个 Aggregate Service 把 4 个类似功能的微服务模块的数据和功能进行整合,提供给分析平台使用。

    这里面每一个服务按照微服务的架构,每一个都是单独部署,在一个独立的容器内执行,并使用自己的一个数据库。

    果不其然,系统上线一段时间后,Mandy 说 Google+ 上面几乎没有什么活动,不值得继续维护这样的一套系统。Jonnathan 这次毫无抱怨,直接把负责 Google+ 的容器停了,没有需要任何代码改动,甚至完全没有需要对整个系统进行停机。

    在这里插入图片描述

    刚下线 Google+,Mandy 又来提需求说最近合并了另一家银行,客户很多使用 Whatsapp。二话不说,Jonnathan 直接上了一个新的模块来处理 Whatsapp ,如下图。

    在这里插入图片描述

    又过了一段时间,这一次是他自己要对系统做调整了,原来 Snapchat 最近大火,他部署的系统频受压力,性能下降。为了解决这个问题,Jonnathan 果断增加了额外 2 台容器来同时支撑 Snapchat 信息的采集和处理。

    在这里插入图片描述

    感谢微服务架构,Jonnathan 在一系列的产品需求变化以及系统扩容需求下,可以从容应付。要实现微服务架构,需要你铭记以下几个微服务架构的应用设计原则。

    解耦

    在微服务架构中,应用程序被分解为小型的独立服务。服务通常专注于特定的离散目标或功能,并沿着业务边界解耦。按业务界限分离服务可让团队专注于正确的目标,并确保服务之间的自主性。

    每项服务都是独立开发,测试和部署的,服务通常是作为独立的进程或软件容器分开的,通过网络和商定的 API 进行通信,尽管在某些情况下,网络可能在本地。通常部署相同微服务的多个实例,从而提供冗余和可扩展性。

    轻量级 API

    微服务之间的通信要使用轻量级 API,如 HTTP RESTful API。这样可以使得服务对 API 通信方案的依赖减到最小。

    复杂的通信处理要在服务端进行,而不是像 ESB 或者 Data Pipeline 处理总线那样在数据传输过程中引入非常多的逻辑,导致微服务模块紧紧的绑定在这个数据管道上。

    持续发布

    微服务架构带来的一个非常显著的负面性就是众多实例的测试发布及管理。传统应用虽然开发复杂,但是部署和运维相对比较集中,一台数据库,2-4 个应用服务器就差不多了。但是微服务架构下单独服务的数量轻则 10-20,多则上百个,所以微服务架构一般需要配套的 CI/CD 方法来支撑。

    数据与治理

    数据的管理在微服务架构下也是和传统单体有很大的不同考量。大部分时候我们希望数据就和服务一样,要有充分的独立性,可以和某个服务一起部署,一起扩展,或者一起重构。

    这通常意味着我们可能要在一个微服务架构应用内使用多个数据库实例。但是同样需要考虑到数据分布在多实例之间以后,往往还需要一些冗余,以及如何保持这些数据在这些系统中的一致性等问题。下面我们就着重来讨论微服务架构下的数据设计的一些考量因素。

    4 微服务架构下的数据设计

    从来没有一个 one-size-fits-all 的架构,所以在微服务架构下面,我们需要了解的,一样是几个关键的架构考量点。然后针对自己的实际应用,选择哪些考量点是更加重要的。

    这篇文章的目的,主要就是跟大家来讨论从哪几个角度着手,来设计一个符合微服务架构原则的数据架构。比如说,我们可以从一系列的问题来开始这个讨论。

    这么多微服务之间,我是否可以用一个数据库,还是多个数据库来支持多个微服务?

    如果是多个数据库,我是否为每一个微服务挑选一个最合适的数据库,还是选择同一种类型的数据库?

    在这里插入图片描述

    当一个我依赖的服务需要修改数据库 Schema 的时候,是否会影响到我?

    当微服务应用不断衍变的时候,我的数据库是否可以快速的响应应用需求变化?以上这些就是我们在微服务数据架构时候要关注的地方。

    一库一服还是一库多服

    无论是单体应用,还是微服务应用,有一点是肯定的:应用的各个模块之间都需要进行较为频繁的通信,通过一起协同合作,来实现应用的整体价值。

    在单体应用中,这种通信是通过方法调用来完成的。在微服务中,则通过 API 调用来完成。这些模块或者服务间调用,大部分时候是为了共享数据。

    共享数据最贱的方式当然就是采用一种共享数据库的模式,也就是单体应用常用的方式。应用可以有多个系统模块,但一般都是只有一个数据库。如下图左边,3 个微服务模块,后面共享一个数据库,简称一库多服务。

    在这里插入图片描述

    这种架构模式通常会被认为是微服务架构下的反范式,它的问题在于:

    单点故障:一个数据库倒下,整批服务全部停止。何来的服务独立性?

    数据在同一个地方,会给贪图方便的开发或者 DBA 工程师编写很多数据间高度依赖的程序或者工具。

    无法针对某一个服务进行精准优化或扩展,如上文所讲的 Snapchat 的例子。

    所以一般推荐的做法,是为每一个微服务准备一个单独的数据库,也即一库一服(Database per Service)模式。如上图右侧所示。这种模式更加适合微服务架构,它满足每一个服务是独立开发、独立部署、独立扩展的特性。

    需要对一个服务进行升级或者数据架构改动的时候,不会影响到其他的服务。需要对某个服务进行扩展的时候,也可以手术式的对某一个服务进行局部扩容。另外,如果某些服务对数据库有特殊的需求,这种模式也为下文所讲的混合持久化(Polyglot Persistence)提供了可能性。

    混合持久化 vs 多模数据库

    混合持久化在大型互联网公司是一个比较风行的模式。它秉承的原则就是为特别的任务提供最好的工具。比如说,如果我希望提供一个高并发低延迟的共享用户会话方案(Shared Session Storage), Redis 可能是一个非常理想的选择。

    如果我是在实现一个产品目录,涉及到大量不定结构的商品数据及属性的建模管理,我可能会采用模式灵活,动态 Schema 的 MongoDB 来作为我的数据库解决方案。如果我希望支持非常强大的全文搜索,ElasticSearch 则是行业中的佼佼者。

    在这里插入图片描述

    微服务的功能分块独立部署为这种架构模式提供了非常好的基础,如上图左侧所示就是个典型的混合持久化的案例:

    混合持久化:Polyglot Persistence

    多模数据库:Multi- model Database

    当然,有句话说的是架构师的工作就是每天做不断的取舍(Trade Off),因为选择往往是让人很纠结。混合持久化的优势很明显,可以让每个单独的服务使用到最佳的工具和技术。

    但是它的弊端也是不容忽视:部署、监控、备份、升级等数据库管理工作从来都是一件困难但是重要的任务。引入多个不同的数据库,也意味着对系统管理维护的复杂度和成本提高了很多。

    这种情况下可能需要比较有资源的公司或者团队才可以使用。这也解释了这个模式为何在大型互联网公司得到较多的采用与推广。

    针对于其他小型规模的用户,或者是缺乏足够掌握各种新型技术人才的公司来说,另一种更为可行的模式可能是多模数据库(Multi-model)。如上图右侧所示,多模数据库的特征是:

    依然是一库一服务(为一个服务部署一个单独的数据库)。

    但是使用的是同一种类型,支持多种场景的数据库,如 NoSQL 中间为功能最全面的 MongoDB。

    虽然是多实例,但是只需维护一种类型的数据库,管理上和人员配备上都较为简单。

    如果你在开发的应用是一款企业级产品,会交付到客户环境部署安装,则运维管理的简单性将在技术选型中占据非常重要的一个比重,无疑这种情况下多模数据库更加适用。

    微服务扩展你的数据

    微服务架构的一大裨益是其灵活的扩展性。以上面的 Snapchat 为例,如果需要采集或处理的数据量快速增长,在我们增加应用服务实例的同时,支撑数据存储的模块也要相应扩充。

    在这里插入图片描述

    AFK Partners 在他们的 Scale Cube 一文里对性能扩展提出了这样的观点,要设计一个真正意义上的可扩展系统,我们必须考虑3个维度,如上图所示:

    X 轴,系统复制(横向扩展)

    Y 轴,非重叠功能的拆分(微服务)

    Z 轴,数据的分区(Sharding)

    一个好的数据架构,在微服务体系内,应该具有同样的可扩展、易扩展性质,从而不给微服务架构拖后腿。关于数据分区扩展有两种做法:

    应用数据分区

    数据库分区

    应用数据分区,顾名思义,就是在应用端对数据的存储进行分区管理。比如说,一个社交应用可以按国家或地区为界把用户的数据分发到不同数据库实例里面。这样的话每个数据库实例只需要存储一部分数据,从而实现海量的数据管理能力。

    数据库分区,就是由数据库的路由节点来完成数据分区的任务。数据库分区的优势是显然的,它对应用透明、扩展快速、无须下线等。如果你的应用有潜在扩充的需求,选择一个能够自动扩展的分布式数据库是一个比较明智的选择。

    动态模式支持及快速开发能力

    这是一个很多架构师可能会忽略,但是非常重要的关注点。我们在迭代式开发 DevOps 微服务上的很多努力,都是为了快速开发,快速上线,以及快速响应变化的需求。

    从数据架构师的角度来看,如何不成为在这个快速开发方法模式中的一个瓶颈,有一个很重要的环节就是是否有一个能够及时响应变化的数据模型。

    传统的数据库都是强模式,需要对 Schema 进行清晰定义, 在需求修改导致模型修改的时候需要对数据库进行模式升级,是一个需要下线、耗时并且是高成本的运维操作。

    在这里插入图片描述

    在新一代的 NoSQL 数据库产生之前,我们并不需要考虑这个问题,但是以 MongoDB、Cassandra 等为代表的 NoSQL 代表的是灵活建模。

    动态支持模式变化的特征使得它们成为敏捷开发和微服务体系内一个有力的竞争者,在选型的时候也是一个重要的考量因素之一。我们说一库一服的架构使得对一个服务的数据库模式修改不会影响到其他服务。

    但是如果使用一个动态模式(有时候有人会说无模式)的数据库,则在该服务本身模式修改的时候也可以最小化运维成本。

    一个适合微服务架构的数据库

    红杉资本的合伙人 Matt Miller 是公认的微服务技术领域专家。他广被传播的“微服务生态图”详尽的列出了微服务架构的相关技术栈。在这里他推荐了 MongoDB 作为主要的数据管理方案。

    在这里插入图片描述

    MongoDB 是一个分布式文档型数据库,它有以下特性使它非常适合于微服务架构,其主要特点包括: 多模数据库(Multi-model)、原生 JSON 数据结构API、动态模式、无模式(Dynamic schema)、数据变化流(Change Stream)、横向扩展能力(Sharding)。

    多模数据库

    MongoDB 从 3.4 版本起在多模数据库场景上提供了不少功能模块,比如说,使用聚合框架。现在开发者可以使用:

    $graphLookup 来实现类似于图数据库的查询。

    $facet 来实现分面搜索。

    内存引擎功能,用于支持类似于 Redis 的高速缓存。

    全文检索,用于实现搜索类型场景。

    动态模式

    这一点一直是 MongoDB 获得开发者青睐的主要原因之一。MongoDB 无须显式的定义数据模式即可让你开始往数据库写入。

    当数据模型有变化时候,比如说在迭代式开发中非常常见的就是增加一些字段,MongoDB 数据库不需要对其进行修改 Schema 操作,而是可以直接在同一个集合(表)里直接写入新版本的文档。这个对于需要实现快速迭代,快速交付的微服务应用开发是一个非常重要的特性。

    在这里插入图片描述

    数据变化流

    微服务架构中由于其分布特性,传统的强事务机制不再适用。数据的一致性一般需要通过一些基于 Event Sourcing 或者事件驱动模型的解决方案。Mongo DB 3.6 版本推出的数据更改流,可以用来实现一个类似于 Kafak 一样的 Message Queue,为各个微服务间的数据协调提供一个简单易用的线程方案。

    横向扩展能力

    MongoDB 一向以其强大的横向扩展能力著称。不少 MongoDB 用户迁移的主要原因就是使用 MongoDB 的 Sharding 技术可以突破关系型数据库在数据量和性能上的瓶颈。

    在这里插入图片描述

    MongoDB 的 Sharding 有几个特征使得其非常适合微服务架构使用:

    弹性扩展:可以扩容也可以缩容。

    无缝扩展:无须停机,就可在线扩容。

    高质量编程视频:shangyepingtai.xin
    自动均衡:无须应用参与即可实现数据的自动均衡,完全透明。一个基于 MongoDB 的微服务参考架构图。
    在这里插入图片描述

    展开全文
  • 定义架构和契约使用 SQL 辅助工具创建数据库将信息输入到数据库数据库读取信息从数据库删除信息更新数据库 您还应阅读 使用数据库 将数据保存到数据库对于重复或结构化数据(比如契约信息) 而言是理想...

    在 SQL 数据库中保存数据

    将数据保存到数据库对于重复或结构化数据(比如契约信息) 而言是理想之选。本课程假定您基本熟悉 SQL 数据库并且可帮助您开始在 Android 中使用 SQLite 数据库。 您在 Android 中使用数据库所需的 API 在 android.database.sqlite 软件包中提供。

    定义架构和契约


    SQL 数据库的主要原则之一是架构:数据库如何组织的正式声明。 架构体现于您用于创建数据库的 SQL 语句。您会发现它有助于创建伴随类,即契约 类,其以一种系统性、自记录的方式明确指定您的架构布局。

    契约类是用于定义 URI、表格和列名称的常数的容器。 契约类允许您跨同一软件包中的所有其他类使用相同的常数。 您可以在一个位置更改列名称并使其在您整个代码中传播。

    组织契约类的一种良好方法是将对于您的整个数据库而言是全局性的定义放入类的根级别。 然后为枚举其列的每个表格创建内部类。

    注意:通过实现 BaseColumns 接口,您的内部类可继承调用的主键字段_ID ,某些 Android 类(比如光标适配器)将需要内部类拥有该字段。 这并非必需项,但可帮助您的数据库与 Android 框架协调工作。

    例如,该代码段定义了单个表格的表格名称和列名称:

    public final class FeedReaderContract {
        // To prevent someone from accidentally instantiating the contract class,
        // give it an empty constructor.
        public FeedReaderContract() {}
    
        /* Inner class that defines the table contents */
        public static abstract class FeedEntry implements BaseColumns {
            public static final String TABLE_NAME = "entry";
            public static final String COLUMN_NAME_ENTRY_ID = "entryid";
            public static final String COLUMN_NAME_TITLE = "title";
            public static final String COLUMN_NAME_SUBTITLE = "subtitle";
            ...
        }
    }

    使用 SQL 辅助工具创建数据库


    在您定义了数据库的外观后,您应实现创建和维护数据库和表格的方法。 这里有一些典型的表格创建和删除语句:

    private static final String TEXT_TYPE = " TEXT";
    private static final String COMMA_SEP = ",";
    private static final String SQL_CREATE_ENTRIES =
        "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
        FeedEntry._ID + " INTEGER PRIMARY KEY," +
        FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
        FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
        ... // Any other options for the CREATE command
        " )";
    
    private static final String SQL_DELETE_ENTRIES =
        "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

    就像您在设备的内部存储中保存文件那样,Android 将您的数据库保存在私人磁盘空间,即关联的应用。 您的数据是安全的,因为在默认情况下,其他应用无法访问此区域。

    SQLiteOpenHelper 类中有一组有用的 API。当您使用此类获取对您数据库的引用时,系统将只在需要之时而不是 应用启动过程中执行可能长期运行的操作:创建和更新数据库。 您只需调用 getWritableDatabase() 或 getReadableDatabase()

    注意:由于它们可能长期运行,因此请确保您在后台线程中调用 getWritableDatabase() 或 getReadableDatabase() , 比如使用 AsyncTask 或IntentService

    要使用 SQLiteOpenHelper,请创建一个 替代 onCreate()onUpgrade() 和 onOpen() 回调方法的子类。您可能还希望实现 onDowngrade(), 但这并非必需操作。

    例如,这里有一个使用如上所示一些命令的 SQLiteOpenHelper 的实现:

    public class FeedReaderDbHelper extends SQLiteOpenHelper {
        // If you change the database schema, you must increment the database version.
        public static final int DATABASE_VERSION = 1;
        public static final String DATABASE_NAME = "FeedReader.db";
    
        public FeedReaderDbHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(SQL_CREATE_ENTRIES);
        }
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // This database is only a cache for online data, so its upgrade policy is
            // to simply to discard the data and start over
            db.execSQL(SQL_DELETE_ENTRIES);
            onCreate(db);
        }
        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            onUpgrade(db, oldVersion, newVersion);
        }
    }

    要访问您的数据库,请实例化 SQLiteOpenHelper 的子类:

    FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());

    将信息输入到数据库


    通过将一个 ContentValues 对象传递至 insert() 方法将数据插入数据库:

    // Gets the data repository in write mode
    SQLiteDatabase db = mDbHelper.getWritableDatabase();
    
    // Create a new map of values, where column names are the keys
    ContentValues values = new ContentValues();
    values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
    values.put(FeedEntry.COLUMN_NAME_TITLE, title);
    values.put(FeedEntry.COLUMN_NAME_CONTENT, content);
    
    // Insert the new row, returning the primary key value of the new row
    long newRowId;
    newRowId = db.insert(
             FeedEntry.TABLE_NAME,
             FeedEntry.COLUMN_NAME_NULLABLE,
             values);

    insert() 的第一个参数即为表格名称。第二个参数指定在 ContentValues 为空的情况下框架可在其中插入 NULL 的列的名称(如果您将其设置为"null", 那么框架将不会在没有值时插入行。)

    从数据库读取信息


    要从数据库中读取信息,请使用 query() 方法,将其传递至选择条件和所需列。该方法结合 insert() 和 update() 的元素,除非列列表定义了您希望获取的数据,而不是希望插入的数据。 查询的结果将在 Cursor 对象中返回给您。

    SQLiteDatabase db = mDbHelper.getReadableDatabase();
    
    // Define a projection that specifies which columns from the database
    // you will actually use after this query.
    String[] projection = {
        FeedEntry._ID,
        FeedEntry.COLUMN_NAME_TITLE,
        FeedEntry.COLUMN_NAME_UPDATED,
        ...
        };
    
    // How you want the results sorted in the resulting Cursor
    String sortOrder =
        FeedEntry.COLUMN_NAME_UPDATED + " DESC";
    
    Cursor c = db.query(
        FeedEntry.TABLE_NAME,  // The table to query
        projection,                               // The columns to return
        selection,                                // The columns for the WHERE clause
        selectionArgs,                            // The values for the WHERE clause
        null,                                     // don't group the rows
        null,                                     // don't filter by row groups
        sortOrder                                 // The sort order
        );

    要查看游标中的某一行,请使用 Cursor 移动方法之一,您必须在开始读取值之前始终调用这些方法。 一般情况下,您应通过调用 moveToFirst() 开始,其将“读取位置”置于结果中的第一个条目中。 对于每一行,您可以通过调用 Cursor 获取方法之一读取列的值,比如 getString() 或 getLong()。对于每种获取方法,您必须传递所需列的索引位置,您可以通过调用 getColumnIndex() 或 getColumnIndexOrThrow() 获取。例如:

    cursor.moveToFirst();
    long itemId = cursor.getLong(
        cursor.getColumnIndexOrThrow(FeedEntry._ID)
    );

    从数据库删除信息


    要从表格中删除行,您需要提供识别行的选择条件。 数据库 API 提供了一种机制,用于创建防止 SQL 注入的选择条件。 该机制将选择规范划分为选择子句和选择参数。 该子句定义要查看的列,还允许您合并列测试。 参数是根据捆绑到子句的项进行测试的值。由于结果并未按照与常规 SQL 语句相同的方式进行处理,它不受 SQL 注入的影响。

    // Define 'where' part of query.
    String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
    // Specify arguments in placeholder order.
    String[] selectionArgs = { String.valueOf(rowId) };
    // Issue SQL statement.
    db.delete(table_name, selection, selectionArgs);

    更新数据库


    当您需要修改数据库值的子集时,请使用 update() 方法。

    更新表格可将insert() 的内容值句法与 delete() 的 where 句法相结合。

    SQLiteDatabase db = mDbHelper.getReadableDatabase();
    
    // New value for one column
    ContentValues values = new ContentValues();
    values.put(FeedEntry.COLUMN_NAME_TITLE, title);
    
    // Which row to update, based on the ID
    String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
    String[] selectionArgs = { String.valueOf(rowId) };
    
    int count = db.update(
        FeedReaderDbHelper.FeedEntry.TABLE_NAME,
        values,
        selection,
        selectionArgs);
    展开全文
  • 微服务的概念最早是 2014 年由 Martin Fowler 和 James Lewis 共同提出,他们定义了微服务是由单一应用程序构成的小服务,拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 ...

    什么是微服务?

    微服务的概念最早是在 2014 年由 Martin Fowler 和 James Lewis 共同提出,他们定义了微服务是由单一应用程序构成的小服务,拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通讯。同时,服务会使用最小规模的集中管理 (例如 Docker)技术,服务可以用不同的编程语言与数据库等。 微服务是SOA架构下的最终产物,该架构的设计目标是为了肢解业务,使得服务能够独立运行。 主要有一下几个特点

    服务拆分粒度更细 微服务可以说是更细维度的服务化,小到一个子模块,只要该模块依赖的资源与其他模块都没有关系,那么就可以拆分为一个微服务。

    服务独立部署 每个微服务都严格遵循独立打包部署的准则,互不影响。比如一台物理机上可以部署多个 Docker 实例,每个 Docker 实例可以部署一个微服务的代码。

    服务独立维护 每个微服务都可以交由一个小团队甚至个人来开发、测试、发布和运维,并对整个生命周期负责。

    服务治理能力要求高 因为拆分为微服务之后,服务的数量变多,因此需要有统一的服务治理平台,来对各个服务进行管理。

    微服务架构下,服务调用主要依赖下面几个基本组件:服务描述 注册中心 服务框架 服务监控 服务追踪 服务治理

    开源RPC框架介绍

    Dubbo

    国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末对外开源,仅支持 Java 语言。中间一度没人维护坑了不少人,17年重启维护焕发新春。架构图如下

    官网: dubbo.io/

    通信框架方面,Dubbo 默认采用了 Netty 作为通信框架。

    通信协议方面,Dubbo 除了支持私有的 Dubbo 协议外,还支持 RMI 协议、Hession 协议、HTTP 协议、Thrift 协议等。

    序列化格式方面,Dubbo 支持多种序列化格式,比如 Dubbo、Hession、JSON、Kryo、FST 等。

    性能: dubbo.apache.org/zh-cn/docs/…

    Tars

    Tars是基于名字服务使用Tars协议的高性能RPC开发框架,同时配套一体化的服务治理平台,帮助个人或者企业快速的以微服务的方式构建自己稳定可靠的分布式应用。
    Tars是将腾讯内部使用的微服务架构TAF(Total Application Framework)多年的实践成果总结而成的开源项目。

    官网:github.com/TarsCloud/T…

    架构图如下

    开源协议为:BSD-3-Clause

    支持多语言 C++,Java,Nodejs,PHP,Go

    性能:github.com/TarsCloud/T…

    gRPC

    一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
    官网:grpc.io

    基于HTTP/2 HTTP/2 提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。gRPC 的协议设计上使用了HTTP2 现有的语义,请求和响应的数据使用HTTP Body 发送,其他的控制信息则用Header 表示。

    IDL使用ProtoBuf gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。

    多语言支持(C, C++, Python, PHP, Nodejs, C#, Objective-C、Golang、Java) gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。

    Motan

    Motan 是国内另外一个比较有名的开源的 RPC 框架,同样也只支持 Java 语言实现,它的架构可以用下面这张图描述。

    Motan 与 Dubbo 的架构类似,都需要在 Client 端(服务消费者)和 Server 端(服务提供者)引入 SDK,其中 Motan 框架主要包含下面几个功能模块。

    register:用来和注册中心交互,包括注册服务、订阅服务、服务变更通知、服务心跳发送等功能。Server 端会在系统初始化时通过 register 模块注册服务,Client 端会在系统初始化时通过 register 模块订阅到具体提供服务的 Server 列表,当 Server 列表发生变更时也由 register 模块通知 Client。

    protocol:用来进行 RPC 服务的描述和 RPC 服务的配置管理,这一层还可以添加不同功能的 filter 用来完成统计、并发限制等功能。

    serialize:将 RPC 请求中的参数、结果等对象进行序列化与反序列化,即进行对象与字节流的互相转换,默认使用对 Java 更友好的 Hessian 2 进行序列化。

    transport:用来进行远程通信,默认使用 Netty NIO 的 TCP 长链接方式。

    cluster:Client 端使用的模块,cluster 是一组可用的 Server 在逻辑上的封装,包含若干可以提供 RPC 服务的 Server,实际请求时会根据不同的高可用与负载均衡策略选择一个可用的 Server 发起远程调用。

    Spring Cloud

    Spring Cloud 是为了解决微服务架构中服务治理而提供的一系列功能的开发框架,它是完全基于 Spring Boot 进行开发的,Spring Cloud 利用 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案。它的架构图可以用下面这张图来描述。

    以下为Spring Cloud的核心功能:

    • 分布式/版本化配置
    • 服务注册和发现
    • 路由
    • 服务和服务之间的调用
    • 负载均衡
    • 断路器
    • 分布式消息传递

    Spring Cloud对于中小型互联网公司来说是一种福音,因为这类公司往往没有实力或者没有足够的资金投入去开发自己的分布式系统基础设施,使用Spring Cloud一站式解决方案能在从容应对业务发展的同时大大减少开发成本。

    下图是RPC框架详细的比较

    如何选择?

    一家A轮融资的公司 原来架构是net,想换java架构。
    公司没有强大的研发实力,公司主要是to B业务,对并发要求不高,那可以试试Spring Cloud 架构, Spring Cloud 不仅提供了基本的 RPC 框架功能,还提供了服务注册组件、配置中心组件、负载均衡组件、断路器组件、分布式消息追踪组件等一系列组件,被技术圈的人称之为“Spring Cloud 全家桶”,而 Dubbo、Motan 基本上只提供了最基础的 RPC 框架的功能,其他微服务组件都需要自己去实现,对于这类研发能力弱的团队,SpringCloud 无疑是最合适的,减少了研发成本,社区热度高,相关的教程文档很多,减少了入门成本;

    再比如这家公司不准备切换Java框架还是继续使用net架构, 有一定的研发能力,对并发要求很高, 那gRPC无疑是最适合的,跨语言支持,高性能;

    没有完美的解决方案,只有最合适的

    推荐阅读

    互联网公司面试必问的Redis题目

    互联网公司面试必问的mysql题目(下)

    学习Java进阶技术干货、实践分享,职位内推,一起聊聊理想。志同道合的朋友,欢迎你的加入。

    展开全文
  • mysql 数据库的逻辑架构图:第一层,即最上一层,所包含的服务并不是MySQL所独有的技术。它们都是服务于C/S程序或者是这些程序所需要的 :连接处理,身份验证,安全性等等。第二层值得关注。这是MySQL的核心部分...
  • 微服务的概念最早是 2014 年由 Martin Fowler 和 James Lewis 共同提出,他们定义了微服务是由单一应用程序构成的小服务,拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 ...
  • 并且,最终说来,产生价值的并不是绚丽的界面和现代化的输入方式,而是存放在数据库中的数据。不幸的是,虽然关系型数据库历经了约30年的发展,有成熟的理论和大量的实践基础,但是,大多数设计、开发人员在设计...
  • 默认情况,SQL Server 将存放路径设置为其安装目录的data子目录,单击该列中的按钮可以打开的“定位文件夹”对话框中更改数据库的存储路径。 完成上述操作后,单击“确定”按钮关闭“新建数据库”窗口,即完成...
  • 多租户技术(Multi-TenancyTechnology)又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。...
  •  3.1.3 diy——solaris手工创建数据库  3.1.4 数据库创建疑难解析  3.2 删除数据库  3.2.1 数据库删除概述  3.2.2 数据库删除——手工篇  3.2.3 数据库删除——dbca篇 第2篇 网 络 管 理  第4章 ...
  •  3.1.3 diy——solaris手工创建数据库  3.1.4 数据库创建疑难解析  3.2 删除数据库  3.2.1 数据库删除概述  3.2.2 数据库删除——手工篇  3.2.3 数据库删除——dbca篇 第2篇 网 络 管 理  第4章 ...
  • 多租户SaaS平台的数据库方案

    千次阅读 2019-02-24 18:14:14
    多租户技术(Multi-TenancyTechnology)又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境 (此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。...
  • SaaS-多租户SaaS平台的数据库方案

    千次阅读 2019-12-27 15:29:30
    多租户技术(Multi-TenancyTechnology) 又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。...
  • 深入浅出MySQL数据库开发、优化与管理维护

    千次下载 热门讨论 2014-01-21 15:48:01
     1.1.1 Windows平台下载MySQL   1.1.2 Linux平台下载MySQL   1.2 MySQL的安装   1.2.1 Windows平台安装MySQL   1.2.2 Linux平台安装MySQL   1.3 MySQL的配置   1.3.1 Windows...
  • 而且还从流程的角度详细讲解了应该如何在数据库系统的架构阶段、设计阶段、开发阶段、部署阶段、运行阶段等各环节中去寻找性能问题的瓶颈和解决方案。 全书一共12章:第1章从系统工程的角度总结了性能问题可以分为...
  • 多租户技术(Multi-TenancyTechnology)又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境 (此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。...
  •  3.1.3 diy——solaris手工创建数据库  3.1.4 数据库创建疑难解析  3.2 删除数据库  3.2.1 数据库删除概述  3.2.2 数据库删除——手工篇  3.2.3 数据库删除——dbca篇 第2篇 网 络 管 理  第4章 ...
  •  3.1.3 DIY——Solaris手工创建数据库  3.1.4 数据库创建疑难解析  3.2 删除数据库  3.2.1 数据库删除概述  3.2.2 数据库删除——手工篇  3.2.3 数据库删除——DBCA篇 第2篇 网 络 管 理  第4章 ...
  • 书中内容主要集中大多数企业常见的问题之上,如安装和升级到oracle database 11g数据库软件、创建数据库、导出和导入数据、数据库的备份与恢复、性能调优,等等。  本书还提供了dba完成本职工作必备的基本的uniix...
  • 1,整个架构:可采用分布式架构,利用微服务架构拆分服务部署不同的服务节点,避免单节点宕机引起的服务不可用! 2,数据库:采用主从复制,读写分离,甚至是分库分表,表数据根据查询方式的不同采用不同的索引比如b...
  • 多租户技术(Multi-TenancyTechnology)又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境 (此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。简单...
  • 多租户技术(Multi-TenancyTechnology)又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。...
  • 1.1 多租户是什么多租户技术(Multi-TenancyTechnology)又称多重租赁技术:是一种软件架构技术,是实现如何在多用户环境 (此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离...
  •  开放平台体系,OAuth协议如何保障ISV对数据的访问是经过授权的合法行为。  3.1 常见的Web攻击手段 128  3.1.1 XSS攻击 128  3.1.2 CRSF攻击 130  3.1.3 SQL注入攻击 133  3.1.4 文件上传漏洞 139  3.1.5...
  • 另外,如果有知道如何做的朋友,希望你们解答的时候把具体的代码帖上来。 因为我对oracle也是知之甚少,所以麻烦各位帮忙实现。 [b]问题补充:[/b] hearken01 兄弟: 你好!很感谢你的回答,我按照你的代码...
  •  在数据库技术日益普及的今天,浅尝辄止的学习显然已经站不住脚,当今企业对于DBA的要求也越来越高,而本书由浅入深循序渐进的讲解正是希望引导读者学习并深入探索Oracle技术。 内容简介  《循序渐进oracle:...
  • 过去几年间,他的工作集中在数据库管理、优化、数据架构规划、解决方案等方面.2007年国内首批OraclecACE,网络ID“Fenng”,长期关注Webc2.0网站架构技术.个人技术Blog:http://dbanotes.net.... 目录 封面 -19 封底 -...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 153
精华内容 61
关键字:

在数据库下如何定义架构