深入分布式缓存-从原理到实践(一)
引言
是《深入分布式缓存-从原理到实践》一书的一些记录
理论基础
cache这个词,据说来自于法语,本意是当CPU处理数据时先到cache中去寻找,如果数据在之前的操作与i就读取而被暂存其中,就不需要从主内存中去读取了.后来cache的范围有所扩展,泛指凡是位于速度相差比较大的两种硬件之间,用于协调两者数据传输差异的结构,都称为cache.
凡是通过两种查询速度较大的方式来查询同一对象都称为cache
缓存:存储在计算机上的一个原始数据复制集,以便用于访问 -wiki
常见的一些缓存:
- CPU多级缓存
- TLB(Translation lookaside buffer) -最新的虚拟内存->物理内存的转换
缓存分类:
- 按缓存位置划分
- 客户端缓存
- 服务器端缓存
- 网络中的缓存
- 按部署方式划分
- 单体缓存
- 集群缓存
- 分布式缓存
网络中的缓存
- web代理缓存
使用正向代理的方式将web服务器上的数据进行缓存,客户端请求后之间返回不需要重新先web服务器请求
- 边缘缓存
边缘缓存是通过反向代理的方式与用户处于同一网络,向用户提供静态内容的缓存,典型应用就是CDN缓存
缓存算法
LRU:最近最少使用算法
LFU:最少使用算法(会统计一段时间内每个缓存的访问次数)
SIZE:缓存大小算法(按照缓存的大小进行算法)
分布式系统理论
- 并向与并发
并发指的是两个事情或多个事情在同一个时间段内间隔发生;并行指的是两个事情或多个事情在同一个时刻同时发生;
- CAP
CAP理论提出一致性\可用性\分区容错性的取舍问题
一致性©:指的是在同一时刻访问所有节点得到的数据相同
可用性(U):指的是在同一时刻访问所有节点得到的数据都可用
分区容错性§:指的是节点一定会发生故障,但是不会影响整个系统的正常运行
分布式系统设计策略
分布式系统设计策略指的是对于设计分布式系统常见的几个问题的处理策略:
- 如何检测你还活着?
- 如何保障高可用?
- 容错机制的设计?
- 重试机制?
- 负载均衡?
下面详细对每一个问题进行解答:
如何检测你还活着?
在分布式系统中如何检测当前节点是否存活?
在大多数分布式中间件中都是通过心跳检测的机制来检测当前节点是否存活的,例如在zk的client与server之间的心跳检测保持连接\redis哨兵架构中的哨兵与master/slave之间的心跳检测
φ-accrual 故障检测器是通过滑动窗口的时间算法来统计结果
Gossip分发(流言算法)通过消息的传递确定节点是否应该停止服务的算法
小结:
存活检测有两个方法:一个是从通信链路入手检测目标节点的网络是否异常\一种是通过检测当前状态是否符合预期状态来检测目标节点是否存活
如何保障高可用?
在分布式系统中保障高可用的核心就是数据备份,通过多个节点的备份来在任何节点故障的情况下提供服务
按照提供服务的节点时机可以分为主备(Master/Slave)<B>互备(Failover)<B>集群(Cluster)这三种方式
-
主备(Master/Slave)模式
主备模式多用于要求严格提供C(一致性)\A(可用性)的场景中,MySQL的主备模式\Redis的哨兵模式 -
互备(Failover)模式
互备模式指的是各个节点提供的数据和服务是相同的,常见的RocketMQ的注册中心NameServer就是多个节点提供相同的服务 -
集群(Cluster)模式
集群模式指的是服务在多个节点运行,不同的节点运行不同的任务,比如Redis的集群模式;集群模式与主备模式/互备模式的区别在于集群模式是仅对服务进行高可用的设计,另外两种设计既有对服务和数据的双重含义
容错机制的设计
容错机制指的是在系统设计中需要对一些异常场景的兼容,例如在Raft的一些实现中就会对CommitId进行CRC32的容错机制校验
重试机制
重试机制指的是系统调用失败后,由于无法确定是否网络异常,或者是否是系统调用的问题,可以重试一定次数,如果重试次数超过限制,则抛出异常;这种设计是基于网络异常和系统异常的区别的基础上来进行设计的,在一般认为中网络异常是频繁且持续的,因此可以重试机制下,重试一定次数
重试机制又会引出接口幂等的场景,因此在分布式系统设计中,接口一定要提供幂等
负载均衡
负载均衡类似于集群模式通过一个总的调度器来对任务进行分配,常用的负载均衡方案Nginx,LB
分布式系统的几个通用问题
- 全局id的生成
- hash取模分配
- 路由表
- 一致性hash算法
- 数据拆分
- 分布式锁的解决方案
- 分布式事务的解决方案
全局Id的生成方案
分布式Id的产生是基于数据服务大都采用集群的模式提供服务,在这种模式下不同的节点如果产生的id不进行相互协调的话会造成id的冲突,因此需要一个全局的id生成方案来保证id的唯一性
有两种实现思路:
- 基于节点执行不同规则的id生成
- 基于全局协调器的id生成
下面分别来介绍一下这两种不同的方案
- 基于节点执行不同规则的id生成
是通过值得数据节点的id生成规则来实现的,例如对id设置初始值和步长,然后每个节点都会计算出自己的id,这样就可以保证id的唯一性
-
基于全局协调器的id生成
基于全局协调器的id生成方案实现比较多,例如通过一张id表的方式来进行实现\通过分布式id生成器的号段模式来实现\通过分布式id生成器的雪花算法来实现 -
snowflake的id生成方案
64bit = 41bit(时间戳) + 10bit(节点id) + 12bit(自增id)
时间戳精确到毫秒
12位自增id每个节点最多产生4096个id
hash取模\路由表\一致性hash算法
hash取模\路由表\一致性hash算法都是为了解决数据或服务的一个寻址过程,例如对于一个数据库来说,如果数据库有多个节点,那么对于某个数据来说,可以通过hash取模的方式来寻址到对应的节点,这样就可以保证数据的一致性
hash取模是指的是对数据进行hash取模,然后根据模的值来寻址到对应的节点,这样就可以保证数据的分片性
路由表是通过预设的路由表来寻址到对应的节点,这样就也可以保证数据的分片性;路由表还有一个优点是对于有序增加的场景下可以通过递增预设的路由表数据来寻址到对应的节点,还不影响之前的数据,但是这样有一个路由表单点问题,需要做好数据的备份和failover
数据拆分
数据的拆分主要指的是将数据分片到不同的节点上,这样就可以保证数据的一致性;前面已经介绍数据拆分的原理;
常用的数据拆分方案是mycat/shardingsphere等
小结
这一章节主要给我们介绍分布式系统设计策略<B>分布式系统的几个通用问题的解决方案