分布式系统的CAP理论:
首先将分布式系统中的三个特性进行如下归纳:
口(一致性(C):在分布式系统中的所有数据备份,在同一时刻是否有同样的值。(等于所有节点访问同一份最新的数据副本)
口可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写求。(对数据更新具备高可用性)
口分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在一定时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。高可用、数据一致是很多系统设计的目标,但是分区又是不可避免的事情,由此引出了
以下几种选择:
(1)CA without P
如果不要求P(不允许分区)则C(强一致性)和A(可用性)是可以保证的。但其分区不是你想不想的问题,而是始终会存在,因此 CA 的系统更多的是允许分区后各子系统依然保持 CA。
典型放弃分区容忍性的例子有关系型数据库、LDAP 等
( 2)CP without A
如果不要求A(可用性),相当于每个请求都需要在 Server 之间强一致,而P(分区)导致同步时间无限延长,如此 CP 也是可以保证的。很多传统的数据库分布式事务都属于这种模式,分布式锁也属于这种情况。
(3) AP wihtout C
要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。
在该证明中,Lynch对CAP的定义进行子更明确的声明:
C:一致性被称为原子对象,任何的读写都应该看起来是“原子”的,或串行的写后面的读一定能读到前面写的内容。所有的读写请求都好像被全局排序。
A:对任何非失败节点都应该在有限时间内给出请求的回应。(请求的可终止性)
P:允许节点之间丢失任意多的消息,当网络分区发生时,节点之间的消息可能会完全丢失。
在Raft 中,任何时候一个服务器可以扮演下面角色之一:
口 领导者:处理所有客户端交互、日志复制等动作,一般一次只有一个领导者
口 选民:类似选民,完全被动的角色,这样的服务器等待被通知投票。
口候选人:候选人就是在选举过程中提名自己的实体,一且选举成功,则成为领导者Raft 算丢分为2个阶段,首先是选举过程,然后在选举出来的领导人带领进行正常操作,比如日志复制等。
步骤展示:
2)其他服务器同意了,回复 OK (同意)指令
此时如果有一个Folower服务器宕机,没有收到求选举的要求,则只要达到半数上的票数,候选人还是可以成为领导者的。
4)如果一旦这个Leader宕机崩溃了,那么 Follower 中会有一个成为候选者,发出邀选举,相当于再次执行 1)~2)的步骤。总结:1)~2)是选举过程,3)是具体协同执行指操作的过程
以Nginx为例,负载均衡有以下几种策略:
*轮询:即Round Robin,根据 Nginx 配置文件中的顺序,依次把客户端的 Web 请求分发到不同的后端服务器。
*最少连接:当前谁连接最少,分发给谁。
*IP地址哈希:确定相同IP 请求可以转发给同一个后端节点处理,以方便 session保持。
*基于权重的负载均衡:配置 Nginx 把请求更多地分发到高配置的后端服务器上,把相对较少的请求分发到低配服务器。
一致性哈希算法是在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法。主要解决单调性(Monotonicity)和分散性(Spread)的问题。单调性简单描述是哈希的结果应能够保证原有已分配的内容可以被映射到原有缓冲中去,避免在节点增减过程中导致不能命中。
按照常用的 hash算法来将对应的 key 哈希到一个具有2^32次方个桶的空间中,即0~(232)-1的数字空间中。现在我们可以将这些数字头尾相连,想象成一个闭合的环形,如
在一致性哈希算法中,如果一台服务器不可用则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其他不会受到影响,
一致性哈希的优点在于可以任意动态添加、删除节点,每次添加、删除一个节点仅影响一致性哈希环上相邻的节点。 为了尽可能均匀地分布节点和数据,一种常见的改进算法是引大虚节点的概念,系统会创建许多虚拟节点,个数远大于当前节点的个数,均匀分布到一致性哈希值域环上。这种增强型方案主要解决平衡性问题,所谓平衡性(Balance)是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。
1. 缓存击穿(Cache Miss):
- 定义: 缓存击穿指的是一个请求查询的数据在缓存中不存在,但在数据库中存在,导致该请求每次都要访问数据库,增加了数据库负载。
- 解决办法:
- 使用互斥锁(Mutex)或分布式锁,确保只有一个线程能够进入数据库查询操作,其他线程等待查询结果。
- 设置短暂的缓存失效时间,避免短时间内多个请求同时查询数据库。
2. 缓存穿透(Cache Penetration):
- 定义: 缓存穿透指的是请求查询的数据在数据库中不存在,每次查询都会穿透缓存直接访问数据库,导致数据库负载过高。
- 解决办法:
- 缓存空对象(Null Object),即使数据库中不存在相应的数据,也将这种情况缓存起来,防止频繁的无效查询,设置空结果的过期时间会很短,最长不超过五分钟。
- 使用布隆过滤器(Bloom Filter)等数据结构,预先过滤掉不存在于数据库中的请求,避免这些请求继续访问数据库。
3. 缓存雪崩(Cache Avalanche):
- 定义: 缓存雪崩指的是缓存中的大量数据同时失效,导致请求直接访问数据库,造成数据库压力激增。
- 解决办法:
- 构建多级缓存架构:nginx缓存 + redis缓存 +其他缓存(ehcache等)
- 设置不同的失效时间,避免缓存同时失效,分散请求对数据库的冲击。
- 互斥锁:
在第一个请求去查询数据库的时候对他加一个互斥锁,其余的查询请求都会被阻塞住,直到锁被释放,从而保护数据库。
降低吞吐量,应用时要慎重。
(1)关系数据库
优势:以完善的关系代数理论作为基础,有严格的标准,支持事务ACID四性,借助索引机制可以实现高效的查询,技术成熟,有专业公司的技术支持
劣势:可扩展性较差,无法较好支持海量数据存储,数据模型过于死板、无法较好支持Web2.0应用,事务机制影响了系统的整体性能等
(2)NoSQL数据库
优势:可以支持超大规模数据存储,灵活的数据模型可以很好地支持Web2.0应用,具有强大的横向扩展能力等
劣势:缺乏数学理论基础,复杂查询性能不高,大都不能实现事务强一致性,很难实现数据完整性,技术尚不成熟,缺乏专业团队的技术支持,维护较困难等
关系数据库和NoSQL数据库各有优缺点,彼此无法取代
关系数据库应用场景:电信、银行等领域的关键业务系统,需要保证强事务一致性
NoSQL数据库应用场景:互联网企业、传统企业的非关键业务(比如数据分析)
Redis(Remote Dictionary Server)是一种开源的内存数据库,它支持多种数据结构,包括字符串(Strings)、哈希表(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets),以及一些高级抽象数据类型如 HyperLogLog、Bitmaps 等。以下是一些常见的Redis数据结构及其应用:
字符串 (Strings):
存储字符串或二进制数据。
常见应用:缓存、计数器、分布式锁。
(字符串,整数,浮点数)
底层实现:int,SDS
哈希表 (Hashes):(map)
存储键值对的散列表。
常见应用:存储对象、用户信息、配置信息。
底层实现:ziplist和hashtable来实现
列表 (Lists):
存储有序的字符串列表。
常见应用:消息队列、最新消息列表、任务队列。
底层实现:linkedlist(双向链表)/ziplist(节省内存占用)
集合 (Sets):
存储无序、唯一的字符串集合。
常见应用:唯一值的存储、共同关注、好友关系。
底层实现:intset/hashtable
有序集合 (Sorted Sets):(zset)
与集合类似,但每个成员都关联一个分数,可以按分数排序。
常见应用:排行榜、范围查询。
底层实现:ziplist/skiplist+hashtable
HyperLogLog:
用于估计基数(集合中不重复元素的数量)。
常见应用:统计独立用户数量、UV(Unique Visitors)计数。
Bitmaps:
位图,可以进行位运算。
常见应用:标记用户是否在线、统计活跃用户。
地理空间索引 (Geospatial Index):
存储地理位置信息。
常见应用:附近的位置搜索、地理围栏。
发布/订阅 (Pub/Sub):
提供消息发布和订阅机制。
常见应用:实时通信、事件通知。
分布式锁:
使用字符串和原子操作实现分布式锁。
常见应用:防止多个客户端同时修改共享资源。
缓存:
将热点数据存储在内存中,提高访问速度。
常见应用:加速读取频繁的数据库查询、API调用。
见书本
Redis提供两种方式进行持久化,一种是 RDB持久化(原理是将Reids在在指定的时间间隔内将存中的数据库数据集快照写入磁盘),另外一种是 AOF(append only file)追加持久化(原理是将Reids的操作日志以追加的方式写入文件)。下面详细介绍这两种方式。
RDB持久化,该方式是指在指定的时间间隔内定时的将内存中的数据集快照写入磁盘,把内存中的数据保存到RDB文件中,是默认的持久化方式。 Redis快照的过程是,首先Redis Server(服务器)使用fork函数复制一份当前进程(父进程)的副本(子进程)。其次,父进程继续接收并处理客户端发来的命令,而子进程将内存中的数据写入硬盘中的临时文件。最后,当子进程写入完所有数据后会将RDB临时文件替换旧的RDB文件。
AOF持久化,追加持久化方式(Append Only File),AOF持久化方式会记录Redis客户端对服务器的每一次写操作命令,并将这些写操作追加保存到appendonly.aof文件中,在Redis服务器重启时,会加载并运行AOF文件里的命令,以达到恢复数据的目的。
见书本
主从复制
哨兵模式
Redis Cluster集群
这次考的是Hash算法解决单节点视频缓存的问题,还有抽奖系统的设计,大家可以大概说一下怎么设计的