目录

漫谈分布式

分布式思想:

类似于hashmap

为什么有hashmap hashtable?

分治思想,提高查找效率。


HDFS

需求:

很多的文件,1000w,放到一台机器上有问题,存不下/访问io瓶颈

解决:集群 node01 node02 node03

文件映射,需要一个管理员记账 x文件->node03,也可以包装成文件目录树 node03/x

细节:

客户单找管理员存一个文件

细节1 是管理员存还是管理员告诉客户端存哪个node?管理告诉客户端存哪个node,否则管理员就成io瓶颈了

分布式里面有角色,大家分工各干自己的事。

细节2 管理员告诉客户端存哪个node,此时要不要记映射(x->node3)?

不要记,因为会存在不一致性问题,管理员记了之后客户端挂了,结果是node3没有x,但是管理员有记映射就有问题。

可以先存个临时映射,不是有效的记录,外接访问看不到,只有存完东西确认后才是有效。

细节3 确认这件事谁发起?node03

管理员相当于主,node相当于从

细节4:同步 副本机制,全量的一对一镜像存储

细节5:大文件 碎片化成几个文件,然后再挨个存,最终散列到各个节点,管理员会记录清单,一个总的文件名下面挂着一个block list。

细节6: 多个客户端,上传可以并行,细粒度锁

细节7:文件整体存和文件分开存有很大的不同效果

镜像副本 vs sharding分片

sharding分片缺点:全量操作 需要从各个节点聚合,优点是分治,更均匀地分散到不同的节点。

细节8:除了存储,还有计算

计算形式? 聚合计算框架 map-reduce

  1. 无关性计算 可以并行计算, 例如过滤,男女 map
  2. 关联性计算 统计,求一个聚合数据 男的个数 reduce

如果是无关性计算可以在各个节点上并行计算,如果是关联性计算需要将各个节点上的数据拉取(shuffle)到某一个节点做统计。

思路:这个世界不止存还有计算,数据分治的话可以达到并行

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200929150151701.png

redis

单机小程序

一台服务器装多个redis实例,redis实例占用内存不能太大,否则持久化会很慢,启动从rdb或aof恢复速度也很快。

这个世界所有技术问题的根源:

  • 单点

    高可用

    主从复制

    • 同步 强一致性 某台从节点挂了, 同步 客户端超时 一致性会破坏可用性
    • 异步 弱一致性,redis默认弱一致性 可能丢数据

    redis 做缓存,弱一致性就不是问题,数据是存在数据库

    评论列表前几页,热数据,只是为了提速而已,真正数据是存在mongodb

    如果做数据库那么就不行

    主从复制 主挂了,可以手动也可以自动,自动就是哨兵机制,客户端连哨兵,哨兵也就是注册发现中心

    哨兵也得做成集群,否则1台挂了就完蛋了。

    哨兵使用的raft协议,实现了paxos论文

    哨兵集群根据raft协议实现了分布式一致性的逻辑,保证了即使某些节点挂了,集群的数据一致性,并且对外提供统一的结果,说白了就是多数派。

    https://gitee.com/lienhui68/picStore/raw/master/null/image-20200929152635703.png

    哨兵和zk很类似,哨兵只给redis服务,zk给其他东西提供服务,转讲zk


    redis设计的时候没有考虑外部分布式的情况,它关注的是自己的内功,5种value,本地方法,用户怎么请求最快,单线程nio,epoll。多机的时候没有考虑主节点挂掉的情况,于是开发了一个哨兵,哨兵类似zk,哨兵集群内部是高可靠高内聚的,可以帮助人

    监控redis的健康状态,帮助人来做主从切换以及告诉客户端应该连谁。这个时候的redis集群(哨兵+主从)才算是一个稍微可靠的集群。

    至于redis主库和从库因为同步有延时 数据存在不一致的问题,常见有这么几种解决方案

    1. 业务可以接受,系统不优化
    2. 强制读主,高可用主库,用缓存提高读性能
    3. 在cache里记录哪些记录发生过写请求,来路由读主还是读从

    如果使用redis cluster的话,最终一致性是由实现gossip协议保证的。

zookeeper

paxos算法允许系统在出现网络分区,只要其中一个分区的节点个数保持过半,对外就能保证可用以及数据的最终一致性(最终所有节点拥有相同的更新),解决单点失败故障的同时,尽可能减少对吞吐量和延迟的影响。

image-20200929161143875

如果客户端使用zk,zk分两个角色(leader/follower)和两个状态(可用/不可用)

客户端增删改,传给主,主再传递给从,对客户端来说,节点是单节点的

这个和redis一样,为啥往redis也写是弱一致的,往zk写就是最终一致的?

两阶段 选主 复制

过半机制

假设有3个节点,一主2从

往zk主节点写数据,zk主节点一个人不算,于是zk主节点将数据传递给其他从节点,当要求写数据节点的个数

3 一致性破坏了可用性

1 弱一致性

2 过半,可以给客户端返回一个成功

此时客户端读不可用的节点会造成数据不一致,zk 分布式集群,里面的角色要两两通信

2 有两层意思(约束)

客户端往zk写,满足过半才算写成功

是否能对外提供服务,势力范围(分区中节点个数)要达到2

如何知道自己的势力范围? 维持心跳通信,势力范围为1就shutdown禁止对外提供服务,降级

此时客户端连接这个节点连接不上,根据连接列表再重新连接其他节点就能取到正确的数据。

所有的从节点必须都要和主节点(主挂了就重新选举)通信,且势力范围要过半,才能对外提供服务。

从节点挂了然后又启动了,需要从主节点同步数据,最终这个节点的数据是一致的,同步的时候状态是不可用的。

zk主节点往从节点同步数据的时候,客户端读从节点的数据也会存在不一致性,zk在一般使用场景下,数据版本可能会取到不一样的情况,但是zk提供了一个同步指令sync,也就是zk可以是弱一致的也可以是最终一致的(强一致),

客户端如果想取集群里一致的数据时,先发出sync同步,sync返回成功后,客户端再告诉zk取哪个数据,sync超时会重新请求另一台zk

如果是4台

4 3 2 1

如果是容忍2台,则有可能出现脑裂,2个分区 各2台的情况,所以4台必须达到3台才行,也就是说只能容忍一台挂掉

只有过半才能防止脑裂的现象。除2+1。

3台容忍一台挂掉,4台也是容忍一台挂掉,所以大家根据经验使用奇数的3 5 7…

主挂了怎么办,选主

官方压测是200ms 可以从剩余的节点中选出一个主节点

怎么选?投票

快速选择,加一个条件。嫡长子

zk给每个节点分配一个数字,zk.1 zk.2 …

存活下来的节点,谁数据版本大就选谁,如果数据版本一样则看谁的sererId大就选哪个

根据这个条件就能很快选出新的主节点。

kafka

分布式的消息队列

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200929163824952.png

消息队列:生产者往里面生产消息,消费者从里面拿走消息进行消费。

分布式的:解决高吞吐,高并发的问题, 多节点

生产者将生产的消息数据弄成3个副本放到3个节点中?

肯定不是这样,sharding,每个分片才会主从,kafka只会从主节点进行消费,kafka不支持主备都对外提供服务,也就是不支持读写分离,只是为了做恢复用的。也可以配置成强一致,数据同步时阻塞。弱一致就可能会失败,和redis多机集群一样。所以采取了折中方案,不支持读写分离。

partition 分区(也称为分片,上图是3个分区)概念,分区有序

如何保证有序性,把两个消息放到一个节点中

分区就有单点的问题,一般会将这个分区的数据副本到其他分区中,也就是分区的数据会互相副本给其他分区。如果该分区挂了再从其他分区恢复。此时就有数据同步的问题,分布式的一致性解决方案,kafka通过zk管理集群配置。

ES

分布式搜索引擎

万变不离其宗,都是“hashmap”