一、一致性 Hash 算法
1、余数 Hash 的缺点
服务器集群扩容,服务器增加,余数改变,导致原来写入到缓存服务器中的数据,无法命中。
基于求余运算解释,即除数发生改变,导致余数发生改变,进而无法得到之前计算的余数。
复制代码
2、一致性 Hash 算法
基于一致性Hash环进行服务器的路由选择
1、建立一致性Hash环
从0到2^32-1范围内的数字首尾相联,也就是正整数的范围,即HashCode范围
2、求出每一个节点的Hash值
每一个节点的Hash值处于环的范围内,然后放到环对应的位置上
3、计算key
针对键值对key-value,把key的hash值计算出来,然后这个key的hash值放到环的位置上,顺时针查找距离key最近的服务器节点,这个服务器就是路由选择的结果
余数hash的缺点在于扩容时,服务器节点增加导致重新计算的hash值无法命中原先计算的hash值,而一致性hash算法,就是用一个极大的数值,将这个除数固定,进而每个数据计算的hash值都是固定的
复制代码
3、一致性 Hash 节点扩容
增加一台新的服务器,计算新节点Node3的hash值,放到换上对应的位置。针对键值对key-value,依然计算key的hash值,落到环的对应位置上,顺时针查找最近的节点
之前设置的键值对key-value,顺时针查找到新的节点上,这时在新节点上,键值对查找不到,便从数据源(即数据库)去查找数据,由于是旁路缓存,数据写回到新的节点上,新增的节点影响的键值对范围较小
余数hash扩容导致大部分的数据无法读取,一致性hash扩容导致一小部分的数据无法读取
复制代码
4、基于虚拟节点的一致性 Hash 算法
一致性hash算法的问题:hash访问负载不均衡/数据存储不均衡
节点在环上的分布,是通过hash值得出的,hash值是一个随机数,极有可能两个节点相邻很近,导致大部分的数据缓存在一个节点上,另一个节点上则没有数据,扩容时会影响大部分的数据
解决办法:
服务器节点虚拟成若干个虚拟节点,把这些虚拟节点放到环上,实践中,一个节点虚拟成150或者200个虚拟节点,均匀地分布在环上
复制代码
5、余数 hash 算法、一致性 hash 算法、基于虚拟节点的一致性 hash 算法的区别
余数hash算法的问题在于不利于扩展,一致性hash算法解决了扩展问题,又产生了均衡问题,基于虚拟节点的一致性hash算法既解决了扩展问题,又解决了均衡问题,影响范围更小,更利于扩展
复制代码
二、常见的缓存实现形式
(1)代理缓存
反向代理缓存,代理数据中心的数据,与代理缓存不同,代理缓存是用户访问站点时,经过代理服务器,代理缓存的数据
多层反向代理缓存
CDN,运营商提供,存储静态内容,CDN价值在于就近提供服务
CDN 同时配置静态文件和动态内容
复制代码
通读缓存(read-through)• 代理缓存,反向代理缓存,CDN 缓存都是通读缓存。• 通读缓存给客户端返回缓存资源,并在请求未命中缓存时获取实际数据。• 客户端连接的是通读缓存而不是生成响应的原始服务器。
旁路缓存(cache-aside)
• 对象缓存是一种旁路缓存,旁路缓存通常是一个独立的键值对(key-value)存储。
• 应用代码通常会询问对象缓存需要的对象是否存在,如果存在,它会获取并使用缓存的对象,如果不存在或已过期, 应用会连接主数据源来组装对象,并将其保存回对象
复制代码
缓存中以便将来使用。
浏览器对象缓存
// 在 WebStorage 中缓存对象的 JavaScript 代码 var preferences = {/* data object to be stored */};localStorage.setItem('preferences', JSON.stringify(preferences));// 访问缓存对象的 JavaScript 代码 var cachedData = localStorage.getItem('preferences');var preferences = JSON.parse(cachedData);
本地对象缓存
• 对象直接缓存在应用程序内存中。
• 对象存储在共享内存,同一台机器的多个进程可以访问它们。
• 缓存服务器作为独立应用和应用程序部署在同一个服务器上。
本地对象缓存构建分布式集群
每台应用服务的缓存数据是一样,容易造成浪费
远程分布式对象缓存
互联网系统主要使用的缓存方式,有利于伸缩,不抢占应用服务器的资源
Memcached 分布式对象缓存
复制代码
//PHP 客户端访问 Memcached 集群m=newMemcached();//添加服务器集群cache->addServers(array(array('cache1.example.com', 11211),array('cache2.example.com', 11211),array('cache3.example.com', 11211)));//写缓存,失效时间 5 分钟 $m->set('userCount', 123, 600);
分布式缓存,每台机器存储的数据不同,存储数据量可以实现幂函数增长,那么,之前说的,不适合存储商品数据,其实,就可以解决了,因为容量变大了
Share-Nothing架构,memcached各个机器之间无法感知对方,彼此之间不进行通信,增加memcached服务器,只需要修改客户端
Memcached 分布式缓存访问模型
有一台memcached挂了,或者增加一台,怎么办?路由算法的问题在哪?
复制代码
三、架构原理与使用中的注意事项
1、缓存
缓存是介于数据访问者和数据源之间的一种高速存储,当数据需要多次读取的时候,用于加快读取的速度,通俗理解,缓存就是访问数据的复制备份
复制代码
缓存 Cache 和缓冲 Buffer 的分别?
共同点:缓存和缓冲都是用在高速与低速设备之间的中间装置
不同点:
(1)缓冲
当读取低速设备的时候,由于低速设备较慢,可以将请求的低速设备的数据写入到一个buffer中,当准备好数据后,再从buffer缓冲里面去读取,然后,buffer就变空了
当写入低速设备的时候,也可以将数据先写入buffer中,待准备好后,再由buffer写入到低速设备上
复制代码
(2)缓存
2、无处不在的缓存
CPU、操作系统、数据库、JVM编译
系统架构重点关注的缓存:CDN、代理与反向代理、前端、应用程序、分布式对象
复制代码
3、各种介质数据访问延迟
4、缓存数据存储原理(Hash 表)
如何获取制定位置数据?
通过hash函数计算出索引值,基于数组头的地址以及每个元素的长度,计算出偏移量,最终得到访问元素的地址
复制代码
5、缓存的关键指标
缓存命中率
• 如果查询一个缓存,十次查询九次能够得到正确结果,那么它的命中率是90%。
• 缓存是否有效依赖于能多少次重用同一个缓存响应业务请求,这个度量指标被称作缓存命中率。
复制代码
6、影响缓存命中率的主要指标
(1)缓存键集合大小
缓存中的每个对象使用缓存键进行识别,定位一个对象的唯一方式就是对缓存键执行精确匹配,从统计数字上看,应用生成的唯一键越多,重用的机会越小。减少缓存键的数量,增加缓存的重复使用率,这样效率才能越高
(2)缓存可使用内存空间
缓存可使用内存空间直接决定了缓存对象的平均大小和缓存对象数量,内存空间越少,一旦达到饱和,新的键值添加进来,就会剔除原来的键值
(3)缓存对象生存时间
缓存对象生存时间称为 TTL( Time To Live )
评论