Open dengdaiyemanren opened 6 years ago
一般来说,影响数据库最大的性能问题有两个,一个是对数据库的操作,一个是数据库中数据的大小。 对于前者,我们需要业务上优化。一方面,简化业务,不要在数据库上做太多的关联查询,而对于一些更为复杂的用于做报表或者搜索的数据库操作,应该把其移到更合适的地方。比如,用ElasticSearch来做查询,用Hadoop或者别的数据分析软件来做报表分析。 对于或者,分库分表是必要的手段。
关于分库策略。 我们把数据库按某种规则分成了三个库。比如,或者按地理位置,或者按日期,或者按某个范围分,或者按一种hash散列算法。总之,我们把数据分到了三个库中。
关于数据库访问层。 需要引入一个叫做“数据访问层”的中间件。解析SQL语句的能力,并且根据解析的SQL路由。 比如要做一个分页功能,需要读一组顺序的数据,或者需要做MAX/MIN/COUNT 这样的操作。需要到三个库中分别求值,然后在数据访问层这里合计处理返回。如果遇到跨库事物,你需要走XA这样两阶段提交操作,这样会把数据库性能降到最低。 一般的分片策略如下:
按多租户的方式。用租户ID来分,这样可以把租户隔离开来。比如:一个电商平台的商家中心可以按商户的ID来分。
按数据的种类来分。比如,一个电商平台的商品库可以按目录来分,或者商家按地域来分。
通过范围来分。这样分片,可以保证在同一个分片中的数据是连续的,于是我们数据库操作,比如分页查询会高效一些。一般来说,大多数情况是用时间来分片,比如一个电商平台的订单中心按月份来分表的,这样可以快速检索和统一一段连续的数据。
通过哈希散列算法来分,可以降低热点的可能性,但是会有2个问题,一个就是跨库跨表的查询和事物问题,另一个就是如果扩容需要重新hash部分或者全部数据。
这里只是业务层上谈一下数据扩展的两种方法,数据库引擎的水平扩展,可以参考《分布式数据调度的相关论文》中的AWS Aurora 和Google Spanner 的那些方法。
一个服务一个库,AWS的玩法。 先做服务化拆分,再做分片。 有两种分片模式,一种是水平分片,一种是垂直分片。水平分片就是我们之前说的那种分片。而垂直分片 是把一张表的一些字段放到一张表中,另一些字段放到另一张表中。垂直分片主要是把一些经常修改的数据和不经常修改的数据给分离开来,这样修改某个字段的数据时,不会导致其他字段的数据被锁而影响性能。比如电商的商品描述信息和库存价格信息分离。 水平分片需要注意的点。
随着数据库中数据的变化,我们需要定期重新平衡分片,以保证均匀分布并降低形成热点的可能性。但是平衡是一项昂贵的操作。若要减少重新平衡的频率,我们需要通过确保每个分片保护足够的可用空间来处理未来一段时间的变化。另外,我们还需要开发用于快速重新平衡分片的工具和脚本。
分片是静态的,而数据的访问则是不可预期的,可能会需要经常的调整我们的分片,这样一来成本太高。所以最好使用一个索引表的方式来进行分片。也就是说,把我们的数据索引动态的记录在一个索引表中。这样一来,我们可以非常灵活的调度我们的数据了。当数据调度到另一台结点上时,我们只需要去索引表里改一下这个数据的位置就好了。
如果程序必须要从多个分片检索数据的查询,则可以使用并行任务从各个分片上提取此数据,然后聚合到单个结果中。但是,此方法不可避免的会在一定程度上增加解决方案数据访问逻辑的复杂性。
数据分片以后,我们很难在分片之间保持引用完整性和一致性,也就是所谓的跨分片的事物,因此应尽量减少会影响多个分片中数据操作。如果应用程序必须跨分片修改数据,那么我们需要评估一致性以及评估是否采用两阶段提交的方式。
配置和管理大量分片可能是一个挑战。在做相应的改变时,一定要从生成线上拉出数据,然后根据数据计划好新的分片方式,并做好相当的测试工作。
VO的实体类型不一样,EntityVO和QueryVO 操作方法不一样,queryByVc, loadUsageByVc
聚合路由功能:DDS层功能模块
某一领域的服务对应自己的库,逻辑上分离。
按照BE,租户水平分库,逻辑上分离,物理上通过同步保持数据一致。 分库携带字段为BE,要求每张分库表都需要携带这个字段,否则会导致SQL下沉不了。 额外的查询需要申明为非分库查询,效率变低。
背景:一个BE下数据量还是很大,一个客户挂靠大量设备。
读写分离 CQRS
CQRS全称Command an Query Responsibility Segregation ,也就是命令与查询职责分离。 其原理是,用户对于一个应用的操作可以分成两种,一种是Command 也就是我们的写操作(增,删,改),另一种是Query操作(查),也就是读操作。Query操作基本上是在做数据整合显现,而Command操作这边会有更重的业务逻辑。分离这两种操作可以在语义上做好区分。
命令Command 不会返回结果数据,只会返回执行状态,但会改变数据。
查询Query 会返回结果数据,但不会改变数据,对系统没有副作用。 这样的好处:
分工明确,可以负责不同的部分
将业务上的命令和查询的职责分离,能够提高系统的性能、可扩展性和安全性。并且系统的演化中能够保持高度的灵活性,能够防止出现CRUD模式中,对查询或者修改中的某一方进行改动,导致另一方出现问题的情况。
逻辑清晰,能够看到系统中的哪些行为或者操作导致系统的状态变化。
可以从数据驱动(Data-Driven)转移到任务驱动(Task-Driven)以及事件驱动。 可以参考CQRS and Event Sourcing Application With Cassandra