主题
高可用存储架构
双机架构
主备复制
备机只起到备份数据的作用,并不承担实际的业务读写操作;如果要把备机改为主机,需要人工操作。常见的 MySQL、 Redis、 MongoDB都实现了主备复制的功能。
优点:架构简单。
缺点:
- 备机只存储数据,硬件成本浪费。
- 故障后需要人工干预。
适用场景:内部的后台管理系统,如学生、员工等管理系统,因为这类数据的变更频率较低,即使数据丢失也可以人工方式补全。
主从复制
主机负责读写操作,从机负责读操作。
优点:
- 主机故障时不影响读操作。
- 充分利用了从机的硬件资源,分摊了主机的一部分读操作压力。
缺点:
- 复杂度较高。
- 如果数据复制延迟较大,会出现数据不一致的问题。
- 故障时需要人工干预。
适用场景:写少读多的业务,如新闻网站、论坛、 BBS等。
主备/主从切换
在主备复制或主从复制的基础上加入主机故障时自动切换主机角色的功能。
设计的关键点:
主备间状态判断
- 状态传递渠道:相互直连还是第三方仲裁
- 状态检测内容:例如机器是否掉电、进程是否存在、响应是否缓慢等。
切换决策
- 切换时机:什么情况下备机应该升级为主机?是机器掉电后备机才升级,还是主机上的进程不存在就升级,还是主机响应时间超过2秒就升级,还是3分钟内主机连续重启3次就升级等。
- 切换策略:原来的主机故障恢复后,要再次切换,确保原来的主机继续做主机,还是原来的主机故障恢复后自动成为新的备机?
- 自动程度:切换是完全自动的,还是半自动的?例如,系统判断当前需要切换,但需要人工做最终的确认操作。
数据冲突问题:当原有故障的主机恢复后,新旧主机之间可能存在数据冲突。
例如,用户在旧主机上新增了一条ID为100的数据,这个数据还没有复制到旧的备机,此时发生了切换,旧的备机升级为新的主机,用户又在新的主机上新增了一条ID为100的数据,当旧的故障主机恢复后,这两条ID都为100的数据,应该怎么处理?
以上关键点没有绝对的标准,需要根据具体业务来设计。
常见架构:
- 互连式:主备机直接建立状态传递的渠道。
- 中介式:在主备两者之外引入第三方中介,主备机之间不直接连接,而都去连接中介,并且通过中介来传递状态信息。如:MongoDB 的 Replica Set;Redis 的单哨兵模式。
- 模拟式:主备机之间并不传递任何状态数据,而是备机模拟成一个客户端,向主机发起模拟的读写操作,根据读写操作的响应情况来判断主机的状态。
主主复制
指的是两台机器都是主机,互相将数据复制给对方,客户端可以任意挑选其中一台机器进行读写操作。
独特的复杂性:必须保证数据能够双向复制,而很多数据是不能双向复制的。如:
- 用户注册后生成的用户ID,如果按照数字增长,那就不能双向复制。
- 库存不能双向复制。
适用场景:主主复制架构对数据的设计有严格的要求,一般适合于那些临时性、可丢失、可覆盖的数据场景。例如,用户登录产生的session数据(可以重新登录生成)、用户行为的日志数据(可以丢失)、论坛的草稿数据(可以丢失)等。
集群架构
多台机器组合在一起形成一个统一的系统。多台至少要3台以上,主备和主从则是2台。
数据集中集群
与主备、主从这类架构类似,也可称为1主多备、1主多从。无论是1主1从、1主1备,还是1主多备、1主多从,数据都只能往主机中写,而读操作可以参考主备、主从架构进行灵活多变。
虽然架构上是类似的,但由于集群里面的服务器数量更多,导致复杂度整体更高一些,具体体现在:
主机如何将数据复制给备机?
- 多条复制通道导致主机压力过大
- 备机之间的数据一致性问题
备机如何检测主机状态?
多台备机都需要对主机状态进行判断,而不同的备机判断的结果可能是不同的,如何处理不同备机对主机状态的不同判断,是一个复杂的问题。
主机故障后如何决定新的主机?
多台备机都可以升级为主机,备机之间应该如何协商
目前开源的数据集中集群以ZooKeeper为典型,ZooKeeper通过ZAB算法来解决上述提到的几个问题,但ZAB算法的复杂度是很高的。
数据分散集群
多个服务器组成一个集群,每台服务器都会负责存储一部分数据;同时,为了提升硬件利用率,每台服务器又会备份一部分数据。需要一个“主机”(与数据集中集群中的主机职责是有差异的)用来负责执行数据分配算法,这个主机可以是单独的服务器(如Hadoop),也可以是集群内部的一台服务器(如Elasticsearch)。
数据分散集群的复杂点在于:如何将数据分配到不同的服务器上?需要考虑以下设计点:
- 均衡性:算法需要保证服务器上的数据分布基本是均衡的,不能存在某台服务器上的数据量是另一台的几倍的情况。
- 容错性:当出现部分服务器故障时,算法需要将原来分配给故障服务器的数据分区分配给其它服务器。
- 可伸缩性:当集群容量不够时,扩充新的服务器后,算法能够自动将部分数据分区迁移到新的服务器,并保证扩容后所有服务器的均衡性。
总结
数据集中集群架构中,客户端只能将数据写到主机;数据分散集群架构中,客户端可以向任意服务器中读写数据。正是因为这个关键的差异,决定了两种集群的应用场景不同。
一般来说,数据集中集群适合数据量不大,集群机器数量不多的场景。例如,ZooKeeper集群,一般推荐5台机器左右,数据量是单台服务器就能够支撑;而数据分散集群,由于其良好的可伸缩性,适合业务数据量巨大、集群机器数量庞大的业务场景。例如,Hadoop集群、HBase集群,大规模的集群可以达到上百台甚至上千台服务器。