auto commit

This commit is contained in:
CyC2018 2019-12-12 01:20:12 +08:00
parent de37d92168
commit 80d6d56074
10 changed files with 290 additions and 290 deletions

View File

@ -55,7 +55,7 @@ l + h 可能出现加法溢出,也就是说加法的结果大于整型能够
**变种** **变种**
二分查找可以有很多变种变种实现要注意边界值的判断例如在一个有重复元素的数组中查找 key 的最左位置的实现如下 二分查找可以有很多变种实现变种要注意边界值的判断例如在一个有重复元素的数组中查找 key 的最左位置的实现如下
```java ```java
public int binarySearch(int[] nums, int key) { public int binarySearch(int[] nums, int key) {

View File

@ -19,20 +19,20 @@
消息生产者向消息队列中发送了一个消息之后只能被一个消费者消费一次 消息生产者向消息队列中发送了一个消息之后只能被一个消费者消费一次
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/206f965e-53b2-4732-90cf-75910b80d7ac.png" width="450px"/> </div><br> <div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011250613.png"/> </div><br>
## 发布/订阅 ## 发布/订阅
消息生产者向频道发送一个消息之后多个消费者可以从该频道订阅到这条消息并消费 消息生产者向频道发送一个消息之后多个消费者可以从该频道订阅到这条消息并消费
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4e93f7d4-2623-4129-a939-59051256561e.png" width="450px"/> </div><br> <div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011410374.png"/> </div><br>
发布与订阅模式和观察者模式有以下不同 发布与订阅模式和观察者模式有以下不同
- 观察者模式中观察者和主题都知道对方的存在而在发布与订阅模式中生产者与消费者不知道对方的存在它们之间通过频道进行通信 - 观察者模式中观察者和主题都知道对方的存在而在发布与订阅模式中生产者与消费者不知道对方的存在它们之间通过频道进行通信
- 观察者模式是同步的当事件触发时主题会调用观察者的方法然后等待方法返回而发布与订阅模式是异步的生产者向频道发送一个消息之后就不需要关心消费者何时去订阅这个消息可以立即返回 - 观察者模式是同步的当事件触发时主题会调用观察者的方法然后等待方法返回而发布与订阅模式是异步的生产者向频道发送一个消息之后就不需要关心消费者何时去订阅这个消息可以立即返回
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/530764d5-f67f-47a2-8df4-57e8646e1400.png" width="450px"/> </div><br> <div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011747967.png"/> </div><br>
# 使用场景 # 使用场景

View File

@ -1,11 +1,11 @@
<!-- GFM-TOC --> <!-- GFM-TOC -->
* [缓存特征](#一缓存特征) * [缓存特征](#一缓存特征)
* [LRU](#二lru) * [缓存位置](#二缓存位置)
* [缓存位置](#三缓存位置) * [CDN](#三cdn)
* [CDN](#四cdn) * [缓存问题](#四缓存问题)
* [缓存问题](#五缓存问题) * [数据分布](#五数据分布)
* [数据分布](#六数据分布) * [一致性哈希](#六一致性哈希)
* [一致性哈希](#七一致性哈希) * [LRU](#七lru)
* [参考资料](#参考资料) * [参考资料](#参考资料)
<!-- GFM-TOC --> <!-- GFM-TOC -->
@ -32,7 +32,141 @@
- LFULeast Frequently Used最不经常使用策略优先淘汰一段时间内使用次数最少的数据 - LFULeast Frequently Used最不经常使用策略优先淘汰一段时间内使用次数最少的数据
# LRU # 缓存位置
## 浏览器
HTTP 响应允许进行缓存时浏览器会将 HTMLCSSJavaScript图片等静态资源进行缓存
## ISP
网络服务提供商ISP是网络访问的第一跳通过将数据缓存在 ISP 中能够大大提高用户的访问速度
## 反向代理
反向代理位于服务器之前请求与响应都需要经过反向代理通过将数据缓存在反向代理在用户请求反向代理时就可以直接使用缓存进行响应
## 本地缓存
使用 Guava Cache 将数据缓存在服务器本地内存中服务器代码可以直接读取本地内存中的缓存速度非常快
## 分布式缓存
使用 RedisMemcache 等分布式缓存将数据缓存在分布式缓存系统中
相对于本地缓存来说分布式缓存单独部署可以根据需求分配硬件资源不仅如此服务器集群都可以访问分布式缓存而本地缓存需要在服务器集群之间进行同步实现难度和性能开销上都非常大
## 数据库缓存
MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率
## Java 内部的缓存
Java 为了优化空间提高字符串基本数据类型包装类的创建效率设计了字符串常量池及 ByteShortCharacterIntegerLongBoolean 这六种包装类缓冲池
## CPU 多级缓存
CPU 为了解决运算速度与主存 IO 速度不匹配的问题引入了多级缓存结构同时使用 MESI 等缓存一致性协议来解决多核 CPU 缓存数据一致性的问题
# CDN
内容分发网络Content distribution networkCDN是一种互连的网络系统它利用更靠近用户的服务器从而更快更可靠地将 HTMLCSSJavaScript音乐图片视频等静态资源分发给用户
CDN 主要有以下优点
- 更快地将数据分发给用户
- 通过部署多台服务器从而提高系统整体的带宽性能
- 多台服务器可以看成是一种冗余机制从而具有高可用性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/15313ed8-a520-4799-a300-2b6b36be314f.jpg"/> </div><br>
# 缓存问题
## 缓存穿透
指的是对某个一定不存在的数据进行请求该请求将会穿透缓存到达数据库
解决方案
- 对这些不存在的数据缓存一个空数据
- 对这类请求进行过滤
## 缓存雪崩
指的是由于数据没有被加载到缓存中或者缓存数据在同一时间大面积失效过期又或者缓存服务器宕机导致大量的请求都到达数据库
在有缓存的系统中系统非常依赖于缓存缓存分担了很大一部分的数据请求当发生缓存雪崩时数据库无法处理这么大的请求导致数据库崩溃
解决方案
- 为了防止缓存在同一时间大面积过期导致的缓存雪崩可以通过观察用户行为合理设置缓存过期时间来实现
- 为了防止缓存服务器宕机出现的缓存雪崩可以使用分布式缓存分布式缓存中每一个节点只缓存部分的数据当某个节点宕机时可以保证其它节点的缓存仍然可用
- 也可以进行缓存预热避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩
## 缓存一致性
缓存一致性要求数据更新的同时缓存数据也能够实时更新
解决方案
- 在数据更新的同时立即去更新缓存
- 在读缓存之前先判断缓存是否是最新的如果不是最新的先进行更新
要保证缓存一致性需要付出很大的代价缓存数据最好是那些对一致性要求不高的数据允许缓存数据存在一些脏数据
## 缓存 无底洞 现象
指的是为了满足业务要求添加了大量缓存节点但是性能不但没有好转反而下降了的现象
产生原因缓存系统通常采用 hash 函数将 key 映射到对应的缓存节点随着缓存节点数目的增加键值分布到更多的节点上导致客户端一次批量操作会涉及多次网络操作这意味着批量操作的耗时会随着节点数目的增加而不断增大此外网络连接数变多对节点的性能也有一定影响
解决方案
- 优化批量数据操作命令
- 减少网络通信次数
- 降低接入成本使用长连接 / 连接池NIO
# 数据分布
## 哈希分布
哈希分布就是将数据计算哈希值之后按照哈希值分配到不同的节点上例如有 N 个节点数据的主键为 key则将该数据分配的节点序号为hash(key)%N
传统的哈希分布算法存在一个问题当节点数量变化时也就是 N 值变化那么几乎所有的数据都需要重新分布将导致大量的数据迁移
## 顺序分布
将数据划分为多个连续的部分按数据的 ID 或者时间分布到不同节点上例如 User 表的 ID 范围为 1 \~ 7000使用顺序分布可以将其划分成多个子表对应的主键范围为 1 \~ 10001001 \~ 2000...6001 \~ 7000
顺序分布相比于哈希分布的主要优点如下
- 能保持数据原有的顺序
- 并且能够准确控制每台服务器存储的数据量从而使得存储空间的利用率最大
# 一致性哈希
Distributed Hash TableDHT 是一种哈希分布方式其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题
## 基本原理
将哈希空间 [0, 2<sup>n</sup>-1] 看成一个哈希环每个服务器节点都配置到哈希环上每个数据对象通过哈希取模得到哈希值之后存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg"/> </div><br>
一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点例如下图中新增节点 X只需要将它前一个节点 C 上的数据重新进行分布即可对于节点 ABD 都没有影响
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66402828-fb2b-418f-83f6-82153491bcfe.jpg"/> </div><br>
## 虚拟节点
上面描述的一致性哈希存在数据分布不均匀的问题节点存储的数据量有可能会存在很大的不同
数据不均匀主要是因为节点在哈希环上分布的不均匀这种情况在节点数量很少的情况下尤其明显
解决方式是通过增加虚拟节点然后将虚拟节点映射到真实节点上虚拟节点的数量比真实节点来得多那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好从而使得数据分布也更加均匀
# LRU
以下是基于 双向链表 + HashMap LRU 算法实现对算法的解释如下 以下是基于 双向链表 + HashMap LRU 算法实现对算法的解释如下
@ -165,140 +299,6 @@ public class LRU<K, V> implements Iterable<K> {
} }
``` ```
# 缓存位置
## 浏览器
HTTP 响应允许进行缓存时浏览器会将 HTMLCSSJavaScript图片等静态资源进行缓存
## ISP
网络服务提供商ISP是网络访问的第一跳通过将数据缓存在 ISP 中能够大大提高用户的访问速度
## 反向代理
反向代理位于服务器之前请求与响应都需要经过反向代理通过将数据缓存在反向代理在用户请求反向代理时就可以直接使用缓存进行响应
## 本地缓存
使用 Guava Cache 将数据缓存在服务器本地内存中服务器代码可以直接读取本地内存中的缓存速度非常快
## 分布式缓存
使用 RedisMemcache 等分布式缓存将数据缓存在分布式缓存系统中
相对于本地缓存来说分布式缓存单独部署可以根据需求分配硬件资源不仅如此服务器集群都可以访问分布式缓存而本地缓存需要在服务器集群之间进行同步实现难度和性能开销上都非常大
## 数据库缓存
MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率
## Java 内部的缓存
Java 为了优化空间提高字符串基本数据类型包装类的创建效率设计了字符串常量池及 ByteShortCharacterIntegerLongBoolean 这六种包装类缓冲池
## CPU 多级缓存
CPU 为了解决运算速度与主存 IO 速度不匹配的问题引入了多级缓存结构同时使用 MESI 等缓存一致性协议来解决多核 CPU 缓存数据一致性的问题
# CDN
内容分发网络Content distribution networkCDN是一种互连的网络系统它利用更靠近用户的服务器从而更快更可靠地将 HTMLCSSJavaScript音乐图片视频等静态资源分发给用户
CDN 主要有以下优点
- 更快地将数据分发给用户
- 通过部署多台服务器从而提高系统整体的带宽性能
- 多台服务器可以看成是一种冗余机制从而具有高可用性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/15313ed8-a520-4799-a300-2b6b36be314f.jpg"/> </div><br>
# 缓存问题
## 缓存穿透
指的是对某个一定不存在的数据进行请求该请求将会穿透缓存到达数据库
解决方案
- 对这些不存在的数据缓存一个空数据
- 对这类请求进行过滤
## 缓存雪崩
指的是由于数据没有被加载到缓存中或者缓存数据在同一时间大面积失效过期又或者缓存服务器宕机导致大量的请求都到达数据库
在有缓存的系统中系统非常依赖于缓存缓存分担了很大一部分的数据请求当发生缓存雪崩时数据库无法处理这么大的请求导致数据库崩溃
解决方案
- 为了防止缓存在同一时间大面积过期导致的缓存雪崩可以通过观察用户行为合理设置缓存过期时间来实现
- 为了防止缓存服务器宕机出现的缓存雪崩可以使用分布式缓存分布式缓存中每一个节点只缓存部分的数据当某个节点宕机时可以保证其它节点的缓存仍然可用
- 也可以进行缓存预热避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩
## 缓存一致性
缓存一致性要求数据更新的同时缓存数据也能够实时更新
解决方案
- 在数据更新的同时立即去更新缓存
- 在读缓存之前先判断缓存是否是最新的如果不是最新的先进行更新
要保证缓存一致性需要付出很大的代价缓存数据最好是那些对一致性要求不高的数据允许缓存数据存在一些脏数据
## 缓存 无底洞 现象
指的是为了满足业务要求添加了大量缓存节点但是性能不但没有好转反而下降了的现象
产生原因缓存系统通常采用 hash 函数将 key 映射到对应的缓存节点随着缓存节点数目的增加键值分布到更多的节点上导致客户端一次批量操作会涉及多次网络操作这意味着批量操作的耗时会随着节点数目的增加而不断增大此外网络连接数变多对节点的性能也有一定影响
解决方案
- 优化批量数据操作命令
- 减少网络通信次数
- 降低接入成本使用长连接 / 连接池NIO
# 数据分布
## 哈希分布
哈希分布就是将数据计算哈希值之后按照哈希值分配到不同的节点上例如有 N 个节点数据的主键为 key则将该数据分配的节点序号为hash(key)%N
传统的哈希分布算法存在一个问题当节点数量变化时也就是 N 值变化那么几乎所有的数据都需要重新分布将导致大量的数据迁移
## 顺序分布
将数据划分为多个连续的部分按数据的 ID 或者时间分布到不同节点上例如 User 表的 ID 范围为 1 \~ 7000使用顺序分布可以将其划分成多个子表对应的主键范围为 1 \~ 10001001 \~ 2000...6001 \~ 7000
顺序分布相比于哈希分布的主要优点如下
- 能保持数据原有的顺序
- 并且能够准确控制每台服务器存储的数据量从而使得存储空间的利用率最大
# 一致性哈希
Distributed Hash TableDHT 是一种哈希分布方式其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题
## 基本原理
将哈希空间 [0, 2<sup>n</sup>-1] 看成一个哈希环每个服务器节点都配置到哈希环上每个数据对象通过哈希取模得到哈希值之后存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg"/> </div><br>
一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点例如下图中新增节点 X只需要将它前一个节点 C 上的数据重新进行分布即可对于节点 ABD 都没有影响
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66402828-fb2b-418f-83f6-82153491bcfe.jpg"/> </div><br>
## 虚拟节点
上面描述的一致性哈希存在数据分布不均匀的问题节点存储的数据量有可能会存在很大的不同
数据不均匀主要是因为节点在哈希环上分布的不均匀这种情况在节点数量很少的情况下尤其明显
解决方式是通过增加虚拟节点然后将虚拟节点映射到真实节点上虚拟节点的数量比真实节点来得多那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好从而使得数据分布也更加均匀
# 参考资料 # 参考资料
- 大规模分布式存储系统 - 大规模分布式存储系统

View File

@ -55,7 +55,7 @@ l + h 可能出现加法溢出,也就是说加法的结果大于整型能够
**变种** **变种**
二分查找可以有很多变种变种实现要注意边界值的判断例如在一个有重复元素的数组中查找 key 的最左位置的实现如下 二分查找可以有很多变种实现变种要注意边界值的判断例如在一个有重复元素的数组中查找 key 的最左位置的实现如下
```java ```java
public int binarySearch(int[] nums, int key) { public int binarySearch(int[] nums, int key) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -19,20 +19,20 @@
消息生产者向消息队列中发送了一个消息之后只能被一个消费者消费一次 消息生产者向消息队列中发送了一个消息之后只能被一个消费者消费一次
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/206f965e-53b2-4732-90cf-75910b80d7ac.png" width="450px"/> </div><br> <div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011250613.png"/> </div><br>
## 发布/订阅 ## 发布/订阅
消息生产者向频道发送一个消息之后多个消费者可以从该频道订阅到这条消息并消费 消息生产者向频道发送一个消息之后多个消费者可以从该频道订阅到这条消息并消费
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/4e93f7d4-2623-4129-a939-59051256561e.png" width="450px"/> </div><br> <div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011410374.png"/> </div><br>
发布与订阅模式和观察者模式有以下不同 发布与订阅模式和观察者模式有以下不同
- 观察者模式中观察者和主题都知道对方的存在而在发布与订阅模式中生产者与消费者不知道对方的存在它们之间通过频道进行通信 - 观察者模式中观察者和主题都知道对方的存在而在发布与订阅模式中生产者与消费者不知道对方的存在它们之间通过频道进行通信
- 观察者模式是同步的当事件触发时主题会调用观察者的方法然后等待方法返回而发布与订阅模式是异步的生产者向频道发送一个消息之后就不需要关心消费者何时去订阅这个消息可以立即返回 - 观察者模式是同步的当事件触发时主题会调用观察者的方法然后等待方法返回而发布与订阅模式是异步的生产者向频道发送一个消息之后就不需要关心消费者何时去订阅这个消息可以立即返回
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/530764d5-f67f-47a2-8df4-57e8646e1400.png" width="450px"/> </div><br> <div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191212011747967.png"/> </div><br>
# 使用场景 # 使用场景

View File

@ -1,11 +1,11 @@
<!-- GFM-TOC --> <!-- GFM-TOC -->
* [缓存特征](#一缓存特征) * [缓存特征](#一缓存特征)
* [LRU](#二lru) * [缓存位置](#二缓存位置)
* [缓存位置](#三缓存位置) * [CDN](#三cdn)
* [CDN](#四cdn) * [缓存问题](#四缓存问题)
* [缓存问题](#五缓存问题) * [数据分布](#五数据分布)
* [数据分布](#六数据分布) * [一致性哈希](#六一致性哈希)
* [一致性哈希](#七一致性哈希) * [LRU](#七lru)
* [参考资料](#参考资料) * [参考资料](#参考资料)
<!-- GFM-TOC --> <!-- GFM-TOC -->
@ -32,7 +32,141 @@
- LFULeast Frequently Used最不经常使用策略优先淘汰一段时间内使用次数最少的数据 - LFULeast Frequently Used最不经常使用策略优先淘汰一段时间内使用次数最少的数据
# LRU # 缓存位置
## 浏览器
HTTP 响应允许进行缓存时浏览器会将 HTMLCSSJavaScript图片等静态资源进行缓存
## ISP
网络服务提供商ISP是网络访问的第一跳通过将数据缓存在 ISP 中能够大大提高用户的访问速度
## 反向代理
反向代理位于服务器之前请求与响应都需要经过反向代理通过将数据缓存在反向代理在用户请求反向代理时就可以直接使用缓存进行响应
## 本地缓存
使用 Guava Cache 将数据缓存在服务器本地内存中服务器代码可以直接读取本地内存中的缓存速度非常快
## 分布式缓存
使用 RedisMemcache 等分布式缓存将数据缓存在分布式缓存系统中
相对于本地缓存来说分布式缓存单独部署可以根据需求分配硬件资源不仅如此服务器集群都可以访问分布式缓存而本地缓存需要在服务器集群之间进行同步实现难度和性能开销上都非常大
## 数据库缓存
MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率
## Java 内部的缓存
Java 为了优化空间提高字符串基本数据类型包装类的创建效率设计了字符串常量池及 ByteShortCharacterIntegerLongBoolean 这六种包装类缓冲池
## CPU 多级缓存
CPU 为了解决运算速度与主存 IO 速度不匹配的问题引入了多级缓存结构同时使用 MESI 等缓存一致性协议来解决多核 CPU 缓存数据一致性的问题
# CDN
内容分发网络Content distribution networkCDN是一种互连的网络系统它利用更靠近用户的服务器从而更快更可靠地将 HTMLCSSJavaScript音乐图片视频等静态资源分发给用户
CDN 主要有以下优点
- 更快地将数据分发给用户
- 通过部署多台服务器从而提高系统整体的带宽性能
- 多台服务器可以看成是一种冗余机制从而具有高可用性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/15313ed8-a520-4799-a300-2b6b36be314f.jpg"/> </div><br>
# 缓存问题
## 缓存穿透
指的是对某个一定不存在的数据进行请求该请求将会穿透缓存到达数据库
解决方案
- 对这些不存在的数据缓存一个空数据
- 对这类请求进行过滤
## 缓存雪崩
指的是由于数据没有被加载到缓存中或者缓存数据在同一时间大面积失效过期又或者缓存服务器宕机导致大量的请求都到达数据库
在有缓存的系统中系统非常依赖于缓存缓存分担了很大一部分的数据请求当发生缓存雪崩时数据库无法处理这么大的请求导致数据库崩溃
解决方案
- 为了防止缓存在同一时间大面积过期导致的缓存雪崩可以通过观察用户行为合理设置缓存过期时间来实现
- 为了防止缓存服务器宕机出现的缓存雪崩可以使用分布式缓存分布式缓存中每一个节点只缓存部分的数据当某个节点宕机时可以保证其它节点的缓存仍然可用
- 也可以进行缓存预热避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩
## 缓存一致性
缓存一致性要求数据更新的同时缓存数据也能够实时更新
解决方案
- 在数据更新的同时立即去更新缓存
- 在读缓存之前先判断缓存是否是最新的如果不是最新的先进行更新
要保证缓存一致性需要付出很大的代价缓存数据最好是那些对一致性要求不高的数据允许缓存数据存在一些脏数据
## 缓存 无底洞 现象
指的是为了满足业务要求添加了大量缓存节点但是性能不但没有好转反而下降了的现象
产生原因缓存系统通常采用 hash 函数将 key 映射到对应的缓存节点随着缓存节点数目的增加键值分布到更多的节点上导致客户端一次批量操作会涉及多次网络操作这意味着批量操作的耗时会随着节点数目的增加而不断增大此外网络连接数变多对节点的性能也有一定影响
解决方案
- 优化批量数据操作命令
- 减少网络通信次数
- 降低接入成本使用长连接 / 连接池NIO
# 数据分布
## 哈希分布
哈希分布就是将数据计算哈希值之后按照哈希值分配到不同的节点上例如有 N 个节点数据的主键为 key则将该数据分配的节点序号为hash(key)%N
传统的哈希分布算法存在一个问题当节点数量变化时也就是 N 值变化那么几乎所有的数据都需要重新分布将导致大量的数据迁移
## 顺序分布
将数据划分为多个连续的部分按数据的 ID 或者时间分布到不同节点上例如 User 表的 ID 范围为 1 \~ 7000使用顺序分布可以将其划分成多个子表对应的主键范围为 1 \~ 10001001 \~ 2000...6001 \~ 7000
顺序分布相比于哈希分布的主要优点如下
- 能保持数据原有的顺序
- 并且能够准确控制每台服务器存储的数据量从而使得存储空间的利用率最大
# 一致性哈希
Distributed Hash TableDHT 是一种哈希分布方式其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题
## 基本原理
将哈希空间 [0, 2<sup>n</sup>-1] 看成一个哈希环每个服务器节点都配置到哈希环上每个数据对象通过哈希取模得到哈希值之后存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg"/> </div><br>
一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点例如下图中新增节点 X只需要将它前一个节点 C 上的数据重新进行分布即可对于节点 ABD 都没有影响
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66402828-fb2b-418f-83f6-82153491bcfe.jpg"/> </div><br>
## 虚拟节点
上面描述的一致性哈希存在数据分布不均匀的问题节点存储的数据量有可能会存在很大的不同
数据不均匀主要是因为节点在哈希环上分布的不均匀这种情况在节点数量很少的情况下尤其明显
解决方式是通过增加虚拟节点然后将虚拟节点映射到真实节点上虚拟节点的数量比真实节点来得多那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好从而使得数据分布也更加均匀
# LRU
以下是基于 双向链表 + HashMap LRU 算法实现对算法的解释如下 以下是基于 双向链表 + HashMap LRU 算法实现对算法的解释如下
@ -165,140 +299,6 @@ public class LRU<K, V> implements Iterable<K> {
} }
``` ```
# 缓存位置
## 浏览器
HTTP 响应允许进行缓存时浏览器会将 HTMLCSSJavaScript图片等静态资源进行缓存
## ISP
网络服务提供商ISP是网络访问的第一跳通过将数据缓存在 ISP 中能够大大提高用户的访问速度
## 反向代理
反向代理位于服务器之前请求与响应都需要经过反向代理通过将数据缓存在反向代理在用户请求反向代理时就可以直接使用缓存进行响应
## 本地缓存
使用 Guava Cache 将数据缓存在服务器本地内存中服务器代码可以直接读取本地内存中的缓存速度非常快
## 分布式缓存
使用 RedisMemcache 等分布式缓存将数据缓存在分布式缓存系统中
相对于本地缓存来说分布式缓存单独部署可以根据需求分配硬件资源不仅如此服务器集群都可以访问分布式缓存而本地缓存需要在服务器集群之间进行同步实现难度和性能开销上都非常大
## 数据库缓存
MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率
## Java 内部的缓存
Java 为了优化空间提高字符串基本数据类型包装类的创建效率设计了字符串常量池及 ByteShortCharacterIntegerLongBoolean 这六种包装类缓冲池
## CPU 多级缓存
CPU 为了解决运算速度与主存 IO 速度不匹配的问题引入了多级缓存结构同时使用 MESI 等缓存一致性协议来解决多核 CPU 缓存数据一致性的问题
# CDN
内容分发网络Content distribution networkCDN是一种互连的网络系统它利用更靠近用户的服务器从而更快更可靠地将 HTMLCSSJavaScript音乐图片视频等静态资源分发给用户
CDN 主要有以下优点
- 更快地将数据分发给用户
- 通过部署多台服务器从而提高系统整体的带宽性能
- 多台服务器可以看成是一种冗余机制从而具有高可用性
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/15313ed8-a520-4799-a300-2b6b36be314f.jpg"/> </div><br>
# 缓存问题
## 缓存穿透
指的是对某个一定不存在的数据进行请求该请求将会穿透缓存到达数据库
解决方案
- 对这些不存在的数据缓存一个空数据
- 对这类请求进行过滤
## 缓存雪崩
指的是由于数据没有被加载到缓存中或者缓存数据在同一时间大面积失效过期又或者缓存服务器宕机导致大量的请求都到达数据库
在有缓存的系统中系统非常依赖于缓存缓存分担了很大一部分的数据请求当发生缓存雪崩时数据库无法处理这么大的请求导致数据库崩溃
解决方案
- 为了防止缓存在同一时间大面积过期导致的缓存雪崩可以通过观察用户行为合理设置缓存过期时间来实现
- 为了防止缓存服务器宕机出现的缓存雪崩可以使用分布式缓存分布式缓存中每一个节点只缓存部分的数据当某个节点宕机时可以保证其它节点的缓存仍然可用
- 也可以进行缓存预热避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩
## 缓存一致性
缓存一致性要求数据更新的同时缓存数据也能够实时更新
解决方案
- 在数据更新的同时立即去更新缓存
- 在读缓存之前先判断缓存是否是最新的如果不是最新的先进行更新
要保证缓存一致性需要付出很大的代价缓存数据最好是那些对一致性要求不高的数据允许缓存数据存在一些脏数据
## 缓存 无底洞 现象
指的是为了满足业务要求添加了大量缓存节点但是性能不但没有好转反而下降了的现象
产生原因缓存系统通常采用 hash 函数将 key 映射到对应的缓存节点随着缓存节点数目的增加键值分布到更多的节点上导致客户端一次批量操作会涉及多次网络操作这意味着批量操作的耗时会随着节点数目的增加而不断增大此外网络连接数变多对节点的性能也有一定影响
解决方案
- 优化批量数据操作命令
- 减少网络通信次数
- 降低接入成本使用长连接 / 连接池NIO
# 数据分布
## 哈希分布
哈希分布就是将数据计算哈希值之后按照哈希值分配到不同的节点上例如有 N 个节点数据的主键为 key则将该数据分配的节点序号为hash(key)%N
传统的哈希分布算法存在一个问题当节点数量变化时也就是 N 值变化那么几乎所有的数据都需要重新分布将导致大量的数据迁移
## 顺序分布
将数据划分为多个连续的部分按数据的 ID 或者时间分布到不同节点上例如 User 表的 ID 范围为 1 \~ 7000使用顺序分布可以将其划分成多个子表对应的主键范围为 1 \~ 10001001 \~ 2000...6001 \~ 7000
顺序分布相比于哈希分布的主要优点如下
- 能保持数据原有的顺序
- 并且能够准确控制每台服务器存储的数据量从而使得存储空间的利用率最大
# 一致性哈希
Distributed Hash TableDHT 是一种哈希分布方式其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题
## 基本原理
将哈希空间 [0, 2<sup>n</sup>-1] 看成一个哈希环每个服务器节点都配置到哈希环上每个数据对象通过哈希取模得到哈希值之后存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/68b110b9-76c6-4ee2-b541-4145e65adb3e.jpg"/> </div><br>
一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点例如下图中新增节点 X只需要将它前一个节点 C 上的数据重新进行分布即可对于节点 ABD 都没有影响
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/66402828-fb2b-418f-83f6-82153491bcfe.jpg"/> </div><br>
## 虚拟节点
上面描述的一致性哈希存在数据分布不均匀的问题节点存储的数据量有可能会存在很大的不同
数据不均匀主要是因为节点在哈希环上分布的不均匀这种情况在节点数量很少的情况下尤其明显
解决方式是通过增加虚拟节点然后将虚拟节点映射到真实节点上虚拟节点的数量比真实节点来得多那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好从而使得数据分布也更加均匀
# 参考资料 # 参考资料
- 大规模分布式存储系统 - 大规模分布式存储系统