高并发架构实战课
HDFS
HDFS,即 Hadoop 分布式文件系统,其架构如下:
- NameNode 负责整个分布式文件系统的元数据管理,也就是文件路径名、访问权限、数据块 ID、存储位置等信息
- DataNode 负责文件数据的存储和读写操作,HDFS 将文件数据分割成若干数据块(Block),每个 DataNode 存储一部分数据块,这样文件就分布存储在了整个 HDFS 服务器集群中
HDFS 的典型应用场景是大数据计算,即使用 MapReduce、Spark 这样的计算框架来计算存储在 HDFS 上的数据。 也可以把 HDFS 用于海量文件数据的存储与访问。
分布式关系数据库
分片的关系数据库,也被称为分布式关系数据库。也就是说,将一张表的数据分成若干片,其中每一片都包含了数据表中一部分的行记录,然后将每一片存储在不同的服务器上,这样一张表就存储在多台服务器上了。通过这种方式,每张表的记录数上限可以突破千万,保存百亿甚至更多的记录。
两种分片方式
采用硬编码的方式,我们在程序代码中直接指定把一条数据库记录存放在哪个服务器上:
使用分布式关系数据库中间件:
MyCAT 是针对 MySQL 数据库设计的,应用程序可以像使用 MySQL 数据库一样连接 MYCAT,提交 SQL 命令。MyCAT 在收到 SQL 命令以后,查找配置的分片逻辑规则。
HBase
分布式关系数据库可以解决海量数据的存储与访问,但是关系数据库本身并不是分布式的,需要通过中间件或者硬编码的方式进行分片,这样对开发和运维并不友好。
HBase 架构如下:
HRegion 是 HBase 中负责数据存储的主要进程,应用程序对数据的读写操作都是通过和 HRegion 通信完成的。
应用程序如果想要访问一个数据,必须先找到 HRegion,然后将数据读写操作提交给 HRegion,而 HRegion 最终将数据存储到 HDFS 文件系统中。由于 HDFS 是分布式、高可用的,所以 HBase 的数据存储天然是分布式、高可用的。
应用程序如果想查找数据记录,需要使用数据的 key。每个 HRegion 中存储一段 Key 值区间 [key1, key2)
的数据,而所有 HRegion 的信息,包括存储的 Key 值区间、所在 HRegionServer 地址、访问端口号等,都记录在 HMaster 服务器上。因此,应用程序要先访问 HMaster 服务器,得到数据 key 所在的 HRegion 信息,再访问对应的 HRegion 获取数据。为了保证 HMaster 的高可用,HBase 会启动多个 HMaster,并通过 ZooKeeper 选举出一个主服务器。
ZooKeeper
CAP 原理认为,一个提供数据服务的分布式系统无法同时满足数据一致性(Consistency)、可用性(Availibility)、分区耐受性(Patition Tolerance)这三个条件。
- 一致性的意思是,每次读取数据,要么读取到最近写入的数据,要么返回一个错误,而不是过期数据,这样就能保证数据一致
- 可用性的意思是,每次请求都应该得到一个响应,而不是返回一个错误或者失去响应,不过这个响应不需要保证数据是最近写入的
- 也就是说,系统需要一直都能正常使用,不会引起调用者的异常,但是并不保证响应的数据是最新的
- 分区耐受性的意思是,即使因为网络原因,部分服务器节点之间消息丢失或者延迟了,系统依然应该是可以操作的
对于一个分布式系统而言,网络失效一定会发生,也就是说,分区耐受性是必须要保证的,那么可用性和一致性就只能二选一。
ZooKeeper 是一个保证数据一致性的分布式系统,它主要通过一个 ZAB 算法(Zookeeper Atomic Broadcast, Zookeeper 原子广播)实现数据一致性。
在实际应用中,客户端程序可以连接任意一个 Follower,进行数据读写操作。
- 如果是写操作,那么这个请求会被 Follower 发送给 Leader,进行如上所述的处理
- 如果是读操作,因为所有服务器的数据都是一致的,那么这个 Follower 直接把自己本地的数据返回给客户端就可以了
很多分布式系统都使用 ZooKeeper 选择主服务器。
- HDFS 中的 NameNode
- HBase 中的 HMaste
布隆过滤器
文件 MD5 重复性检查的布隆过滤器原理如下:
在一个有很多台服务器的分布式集群中,如何知道数据存储在哪台服务器上?
- 一种是有专门的服务器记录数据存储在哪里,即有一个元数据服务器
- HDFS 里的 NameNode
- HBase 里的 HMaster
- 另一种解决方案是通过某种算法计算要访问的数据的位置,这种算法被称作数据路由算法
- MyCAT
- RedisCluster
消息队列高手课
Kafka 消费模型的几个要点:
- Kafka 的每个 Consumer(消费者)实例属于一个 ConsumerGroup(消费组)
- 在消费时,ConsumerGroup 中的每个 Consumer 独占一个或多个 Partition(分区)
- 对于每个 ConsumerGroup,在任意时刻,每个 Partition 至多有 1 个 Consumer 在消费
- 每个 ConsumerGroup 都有一个 Coordinator (协调者)负责分配 Consumer 和 Partition 的对应关系,当 Partition 或是 Consumer 发生变更时,会触发 rebalance(重新分配)过程,重新分配 Consumer 与 Partition 的对应关系
- Consumer 维护与 Coordinator 之间的心跳,这样 Coordinator 就能感知到 Consumer 的状态,在 Consumer 故障的时候及时触发 rebalance
Kafka 在文档中明确地注明了 Consumer 不是线程安全的,意味着 Consumer 被并发调用时会出现不可预期的结果。为了避免这种情况发生,Kafka 做了主动的检测并抛出异常,而不是放任系统产生不可预期的情况。
|
|
Kafka“主动检测不支持的情况并抛出异常,避免系统产生不可预期的行为”这种模式,对于增强的系统的健壮性是一种非常有效的做法。如果你的系统不支持用户的某种操作,正确的做法是,检测不支持的操作,直接拒绝用户操作,并给出明确的错误提示,而不应该只是在文档中写上“不要这样做”,却放任用户错误的操作,产生一些不可预期的、奇怪的错误结果。
在订阅的实现过程中,Kafka 更新了订阅状态 subscriptions 和元数据 metadata 中的相关 topic 的一些属性,将元数据状态置为“需要立即更新”,但是并没有真正发送更新元数据的请求,整个过程没有和集群有任何网络数据交换。
后端技术面试 38 讲
如果你为需求变更而进行了设计,但是预期中的需求变更却从来没有发生过,那么你的设计就属于设计过度;如果已经发生了需求变更,但是你却没有用灵活的设计方法去应对,而是通过硬编码的方式在既有代码上打补丁,那么这就是设计不足。
是否要使用各种设计原则和设计模式去设计一个非常灵活的程序,主要是看你的需求场景。
对于软件开发而言,复杂的永远是业务逻辑,而不是设计模式。设计模式是可重复的,可重复的东西即使看起来复杂,熟悉了就会觉得很简单。
我们为什么睡觉
睡眠不足并不会使大脑陷入负面情绪状态,并使其保持这种状态。相反,睡眠不足的大脑会过度地在情绪效价的两个极端——正的和负的——之间来回摆动。
极端状态常常是危险的。例如,抑郁和极度消极的情绪可以向一个有价值感的个体注入对生命价值的质疑。
任何一种严重的精神疾病,都伴随着不正常的睡眠状况。抑郁症、焦虑症、创伤后应激障碍(PTSD)、精神分裂症和双相情感障碍 (一度被称为躁狂抑郁症)都是如此。
许多受精神心理障碍影响的大脑区域,正是那些涉及睡眠调节和被睡眠不足影响的区域。
双相情感障碍患者则相反,他们会在情绪频谱的两个极端之间摇摆不定,经历狂躁的危险时期(表现出过激的、奖励驱动的情绪行为)及深度抑郁时期(充满负面情绪和感情)。
睡眠不足是躁狂症或抑郁症精神病的发作透因。
睡眠障碍几乎总是发生在躁郁症患者从病情稳定转变为不稳定的躁狂或抑郁状态之前,可能是这种紊乱的触发器,而不是简单的附属品。
重性抑郁症与正面情绪的缺乏有关,这是一种被描述为快感缺乏的特征:无法从正常的愉悦体验(如食物、社交或性)中获得快乐。
“绝望和希望之间的最佳桥梁是一场良好的睡眠”—— E. Joseph Cossman