共计 4050 个字符,预计需要花费 11 分钟才能阅读完成。
导读 | MySQL 本身不是分布式系统,其支持的数据复制技术,本质上是为了数据容灾使用,但目前基于主从复制进行读写分离,减少单机的读压力。 |
数据存储资源是系统中最重要的组成部分,数据即一切,尤其分布式领域,主要关注以下几点:
- 高可用性,当遇到网络或者系统故障时,系统仍然保持可用
- 高扩展,当数据规模变大时,数据存储系统能够自动适应这种变化
- 高性能,当数据规模和访问规模变大时,性能不受大的影响
- 成本,通过成本反映出系统设计是合理的
- 安全,遇到各种系统和人为故障时,数据不丢失
MySQL 是 OLTP 关系型数据库,支持 ACID 事务,是最主要的存储系统,目前使用的版本是 5.7。MySQL 本身不是分布式系统,其支持的数据复制技术,本质上是为了数据容灾使用,但目前基于主从复制进行读写分离,减少单机的读压力。
MySQL 服务如果托管在阿里云,可以使用高可用版本,秒级的主从切换,基于云盘的磁盘扩容技术,能够快速复制一个只读节点,减少了很多自建 MySQL 遇到的各种问题,另外其还提供了很多额外的功能,比如索引分析、SQL 审查、慢查询分析、动态扩容。
虽然云托管 RDS,但本质上还是 MySQL,仍然会遇到很多问题,比如:
- 数据存储不支持分片,只能通过分库分表的方式进行横向扩展,目前应用层也不支持分库分表的路由,即使分表,拆分表的时候还是会遇到很多问题
- 如果表设计和索引设计不合理,大量的更新,仍然会遇到主从延迟的问题,从应用层面是很难彻底解决的
- 阿里云 RDS 只支持一个负载均衡主从分离,所以后台、队列应用使用 360 Atlas 读写分离服务,目前是一个单点,且也会影响读写性能。
- MySQL 应用规范目前还没有建立,比如什么样的应用应该选择 MySQL,使用 MySQL 很大程度是为了事务,如果没有事务的场景是否可以选择其他的数据库?
- 阿里云官方提到,单表记录数超过 500w,性能会极具下降
- DDL 操作,尤其对于大表操作,会引起很大的同步延迟问题
云托管的 RDS 本质上还是基于 ECS+ 云盘搭建的,数据的增长、备份、性能、迁移、升级、只读实例、磁盘容量、Binlog 延迟还是会显露出来。
那未来如何?其实云厂商也在探索,提出了云原生数据库、云原生分布式数据的概念,比如阿里云的 PolarDB、PolarDB-X。云原生数据库关注成本、性能、在线业务扩展、数据安全,它的核心技术包括计算和存储分离,物理复制 Binlog 行复制模式,共享存储设备,存储之间通过 RDMA 高速网络协议传输,同时 PolarDB- X 支持分区模式,解决了分库分表的问题。
经过这些创新,传统 MySQL 的弊端被解决了,比如同步延迟、备份、成本、分库分表、性能。未来,可以将核心数据库迁移至云原生数据库,保障核心业务的稳定性和扩展性,而对于非 OLTP 业务可以选择其他数据库,且制定 MySQL 应用规范,明确哪些业务模式使用 MySQL,索引正确设计、容量规划、SQL 语句使用规范等等。
Redis 是 K / V 数据库,它基于单线程、内存操作,所以性能非常高。另外支持丰富的数据结构,比如字符串、Hash、List、集合,应用场景非常广泛。它通过 AOF 和 RDB 保障数据持久化,通过复制技术进行数据备份,也支持通过哨兵和分区提供高可用性和容量伸缩,通过 LUA 脚本支持多条命令的事务操作。
Redis 虽然是一个单机系统,但通过复制、集群技术也可以认为是一个分布式存储系统,目前西五街在大量使用,主要分为三类应用:
- 存储,比如用户积分、文章数等数据,这些数据不能丢
- 缓存,比如用户文章列表数据,需要考虑缓存穿透和雪崩等问题
- 消息队列,目前逐步替换为 Kafka 等纯消息系统
阿里云云托管 Redis 社区版 5.0 服务集群版。
在应用设计上存在以下几个问题:
- 存储和缓存混合使用,无法拆分,对于容量估算不透明
- 应用模式上,没有很好的规范,比如缓存更新机制标准、统一 Lib 应用包
通过阿里云 Redis 提供的部署架构,可以很好的理解它的应用场景:
- 标准版 - 双副本:服务可靠,数据可靠,比较标准的使用模式,不管是存储还是缓存服务都可用
- 集群版:通过代理模式和分片可以构建出一个可伸缩的集群模式,解决 Redis 自身单线程瓶颈,满足大容量、高性能的业务需求,而且副本集主要做恢复用,很适合存储场景,不存在同步延迟的问题
- 读写分离架构:对于不关注同步延时的问题,比如缓存场景,可以选择这种模式,当容量不够的适合,通过客户端的一致性 Hash 技术扩容多个 Redis 实例就可以
后续确定 Redis 使用规范,拆分存储和缓存场景,基于统一 Lib 包,就能解决大部分问题。
Elasticseach 是一个近实时的分布式搜索引擎和分析引擎。作为一个搜索引擎,目前在开源领域已经是排名第一的数据库了;基于倒排索引,具有很强的检索能力,所以不管是应用还是在大数据领域,它都是一个非常通用的分析引擎。
近实时表示 Elasticseach 应用场景必须要有所了解,它不支持 ACID,所以无法是一个 OLTP 数据库,但使用压力小了很多,在做策略分析、后台应用、即时查询上有很广泛的场景。作为一个分布式应用,通过副本集机制解决高可用的问题,能够解决单机故障的问题,但如果数据被误删除,还是需要有备份机制,比如 Elasticseach 的快照机制。
副本集的同步最终达到一致性,为了写入性能,也可以配置主节点写入完成即返回给客户端。在容量可扩展方面,可以采用分片机制解决容量横向伸缩的问题,将数据分到不同节点的不同分片上,如果要调整分片,需要 reindex。
在性能方面,通过多副本集节点分担查询压力。也可以使用专门的 Transport 节点分担 date Node 节点的压力,将分片查询,副本查询等路由和合并动作的结果汇总起来。Elasticseach 是 ELK 解决方案的一部分,其还包括很多服务,包括 Filebat,Kibana,Logstash,在大数据领域也是很好的一个方向。Elasticseach 是在 ELK 上搭建的三节点服务,由于规模问题,目前也很少使用分片技术。核心是文章大宽表,用户大宽表。结合了搜索场景和分析场景,通过 Binlog+Canal+Kafka+Go 服务将 MySQL 多个表汇总到一个大宽表,主要是文章信息的大宽表,一方面是满足搜索场景,另外满足策略和应用场景。
现在大宽表的应用模式非常多,基于 Free Schema 模式,查询模式非常灵活,通过订阅方式同步数据,也减轻了应用层的负担,数据正确性有很大的保障。未来,对于 Elasticseach 的应用,一方面要加强性能调优,比如分片数据的不均匀,查询性能的优化,同时要提升可维护性,比如挖掘 reindex、alias 等功能,充分理解 Elasticseach。而在国内的云厂商中,都没有对 Elasticseach 做太大的升级,基本上就是将 Elasticseach 服务托管到云中。
Kakfa 是一个分布式的高吞吐消息队列,订阅 / 消费模式追求的是高性能,而非存储容量。但其日志本身具有重放功能,也可以理解为一个分布式存储系统。
Kafka 的核心功能包括:解耦、消峰、缓存,应用场景极为广泛,是系统不可缺少的一个组件。作为分布式系统,它也有副本和分区机制,从而保障高可用和高吞吐。通过 segment 顺序写,保障了写性能非常高,而基于消费组组的概念,消费者吞吐能力也能横向扩展。同时每个 broker 都能负责查询,提升了吞吐能力。Kafka 基于 Zookeeper 做很多分布式管理功能,包括 Leader 选举,负载均衡,Meta 存储。目前 Kafka 三节点集群是通过 ECS 自行搭建的,运行近一年,服务相对稳定,可维护性也较好,没有太多的管理工作,很多核心服务都已经使用了 Kafka 队列,后续原有基于 Redis 的队列也可以尽快迁移。
MongoDB 是一个分布式的文档数据库,其目标是一个支持 ACID 事务的分布式数据库,因为是面向文档,所以模式非常灵活,结构松散,使用场景很规范,相比 MySQL,其二进制的存储模式,压缩比非常高,存储成本会大幅减少,同时基于 WiredTiger 引擎,能够创建各种类型的索引,甚至子文档也能创建索引,从而提升查询性能
MongoDB 通过 oplog 技术支持副本集,也支持分区,分区键可以自定义,因为有了分区,所以额外有了 mongos 路由服务器,config 服务器,mongos 路由服务器通过查询 config 服务器,向节点和分区发送服务。MongoDB 将一致性和性能诉求交给了客户端,通过 read concern、write concern、read perference 技术提供多种灵活性,比如你要求强一致性,那么就采用 majority,你要求数据永远不丢失就配置 journal 为真。MongoDB 4.0 和 MongoDB 4.2 支持多文档的事务,分别支持复制集、分区维度的事务性,但使用和理解非常复杂,可能是分布式系统中最难学习的部分。
这样说明,不用刻意使用事务,对 MongoDB 进行良好的建模,做 OLTP 关系数据的补充,其在性能、成本、高可用、伸缩性方面是有优势的。其实在 MySQL 中,目前我们也很少使用跨表,跨语句的事务,所以不要太迷信事务,选择好应用场景。除了查询,MongoDB 也支持各种聚合操作,在分析领域也很有广泛的使用场景,这一点和 Elasticseach 很类似。
目前 MongoDB 三节点集群是通过 ECS 自行搭建的,存储规模较小,使用场景较少。对比 MySQL 和 Elasticseach,MongoDB 还是有很广泛的应用场景,比如分析场景,对事务要求不高的场景,数据增长比较大的场景(比如私信数据),业务模式比较灵活的场景(比如各种条件的查询,聚合操作)。不过和 Elasticseach 一样,各大云厂商一样,只是将这个服务托管到云,并没有做太多的优化。