300分钟吃透分布式缓存——陈波 分布式缓存 01 业务数据访问性能太低怎么办? 缓存的定义 狭义缓存 加速CPU数据交换的存储器。 广义缓存 数据高速交换的存储介质,加速数据访问。 降低网络拥堵 减轻服务负载 增强可扩展性 缓存也可以弹性伸缩 缓存的代价 任何事情都有两面性,缓存也不例外。 服务系统中引入缓存,会增加系统的复杂度。 由于缓存相比原始DB存储的成本更高。 参考 300分钟吃透分布式缓存 02 如何根据业务来选择缓存模式和组件? 但是这期间的查询操作,还是要自行创建缓存。异步创建缓存还可以进行预读,缓存附近的内容,空间局限性原理。也可以通过MQ来做。 热数据友好,写操作时更新缓存,而不是删除缓存。
(2)减轻网络压力:本地缓存能够降低对远程服务器的访问次数,从而减轻网络压力,提高系统的可用性和稳定性。 (2)数据一致性问题:由于本地缓存是独立的,与远程服务器存在一定的时间延迟,可能导致数据一致性问题。 (3)维护成本高:随着数据量的增长,本地缓存的维护和管理成本也会相应增加。 三、分布式缓存 分布式缓存概述 分布式缓存是指将数据存储在多个分布式节点上,通过协同工作来提供高性能的数据访问服务。分布式缓存通常使用集群方式进行部署,利用多台服务器来分担数据存储和访问的压力。 (2)数据一致性高:通过分布式一致性协议,分布式缓存能够保证数据在多个节点之间的一致性,减少数据不一致的问题。 (3)易于维护:分布式缓存通常采用自动化管理方式,能够降低维护成本和管理的复杂性。 (2)网络开销大:由于分布式缓存需要通过网络进行数据传输和协同操作,因此相对于本地缓存来说,网络开销较大。
Service Name Service Status Version Info ——————– ———— ————– ———— SCMCORE2: ;且缓存主要主机不能少于三台,微软的说法是少于为了缓存群集保持可用,大多数主 要主机必须保持可用。 仅正常的缓存主机操作。 true true 主要主机执行群集管理角色。这是主要主机。 正常的缓存主机操作,并与其他主要主机一起管理群集。 缓存客户端安全设置 与缓存群集安全设置一样,缓存客户端可以使用 securityProperties 元素在应用程序配置文件中配置安全设置。 有关详细信息,请参阅应用程序配置设置(Windows Server AppFabric 缓存)。 缓存客户端和缓存群集使用启用连接的安全设置,这一点非常重要。
4 分布式缓存 分布式缓存是指将缓存数据分布在多台机器上,以提高缓存容量和并发读写能力的缓存系统。 同时,缓存数据对于应用来讲都是共享的。 2、高可用性 由于数据被分布在多台机器上,即使其中一台机器故障,缓存服务也能继续提供服务。 但是分布式缓存的缺点同样不容忽视。 2、复杂性 分布式缓存需要考虑序列化、数据分片、缓存大小等问题,相对于本地缓存而言更加复杂。 笔者曾经也认为无脑上缓存 ,系统就一定更快,但直到一次事故,对于分布式缓存的观念才彻底改变。 于是,开源中国开发了多级缓存框架 J2Cache,使用了多级缓存 Ehcache + Redis 。 2、由于步骤1已经对本地缓存预热,后续请求直接读取本地缓存,返回给用户端。
写缓冲 无处不在的缓存 操作系统缓存 CPU缓存 JVM缓存 数据库缓存 CDN缓存 反向代理缓存 前端缓存 应用程序缓存 分布式对象缓存 缓存本身的数据结构 tree hash 缓存命中率 缓存是否有效依赖于能多少次重用同一个缓存来响应业务请求 对象直接缓存在应用程序内存中 对象存储在共享内存,同一台机器的多个进程可访问 缓存服务作为独立应用和应用程序部署在同一个服务器上,通过localhost访问 分布式对象缓存 分布式寻址算法是分布式对象缓存的关键 当新增节点或某个节点故障时,会有大量key的缓存失效,给数据库带来压力。 一致性hash算法 解决分布式缓存集群扩容时数据访问不一致问题的算法,防止缓存雪崩。 )大概耗时0.5ms 加索引的数据库的一次请求(1-2k)大概耗时50ms,是缓存的100倍 技术栈各个层次的缓存 缓存为什么显著提升性能 缓存数据通常来自内存,比磁盘等其他介质有更快的访问速度 缓存的数据通常是终态 频繁修改的数据 此类型数据应用还来不及读取就失效了徒增系统负担,一般数据的读写比在2:1以上,缓存才有意义。
代码下载:https://gitee.com/hong99/spring/issues/I1N1DF 背景 继上文《spring的缓存(cache)-本地》,本文实现集中式缓存(分布式); redis 地址:http://localhost:8082/user/findById/1 结果:发现已实现了分布式缓存,不会再去查库了,而是直接返回redis结果。 再试试:http://localhost:8082/user/findById/2 结果:发现第一次请求了数据库并且缓存到了redis中,第二次后都是直接查询redis数据 第一次: 17:59:14.999 http://localhost:8081/user/handlerById/2 结果:每次都从缓存中取,给力。 redis在高可用、高并发、高性能基本都杠杠的,当然也引发缓存穿透、缓存击穿、缓存雪崩、热点数据等问题。
还有一个必要软设施:一致性哈希算法提供分布式的负载均衡计算。 ? client的作用 1. 在应用端提供访问Tair集群的接口 2.更新并缓存数据分布表和invalidserver 地址等 3. 本地缓存,避免过热数据访问影响Tair集群服务 4. 并在迁移过程中保持原数据对外提供服务 2. 负载均衡,并行多个key进行计算合并结果(mget) Tair的使用场景 缓存 分布式锁 作为nosql数据库,提供简单类型存储(K/V存储,无复杂查询) Tair使用QA 1.Q:tair可以支持支持什么类型 3.Q:tair的分布式锁使用有什么最佳实践? A:分布式锁使用建议使用带有过期时间的分布式锁,过期时间可传一个绝对的时间戳。解锁时可传入一个非常大的整数,以解掉所有的锁。
答:1.将16384个插槽分配到不同的实例;2.根据key的有效部分计算哈希值,对16384取余;3.余数作为插槽,寻找插槽所在实例即。。如何将同一类数据固定的保存在同一个Redis实例?
分布式缓存设计 目前常见的缓存方案都是分层缓存,通常可以分为以下几层: NG 本地缓存,命中的话直接返回。 NG 没有命中时则需要查询分布式缓存,如 Redis 。 如果分布式缓存没有命中则需要回源到 Tomcat 在本地堆进行查询,命中之后异步写回 Redis 。 以上都没有命中那就只有从 DB 或者是数据源进行查询,并写回到 Redis 中。 可以有以下解决方案: 可以将多个 Tomcat 中的数据写入到 MQ 队列中,由消费者进行单线程更新缓存。 利用分布式锁,只有获取到锁进程才能写数据。 如何写缓存 写缓存时也要注意,通常来说分为以下几步: 开启事务。 写入 DB 。 提交事务。 写入缓存。 这里可能会存在数据库写入成功但是缓存写入失败的情况,但是也不建议将写入缓存加入到事务中。 更新缓存时也建议做增量更新。 负载策略 缓存负载策略一般有以下两种: 轮询机制。 一致哈希算法。 轮询的优点是负载到各个服务器的请求是均匀的,但是如果进行扩容则缓存命中率会下降。
还有一个必要软设施:一致性哈希算法提供分布式的负载均衡计算。 ? client的作用 1. 在应用端提供访问Tair集群的接口 2.更新并缓存数据分布表和invalidserver 地址等 3. 本地缓存,避免过热数据访问影响Tair集群服务 4. 并在迁移过程中保持原数据对外提供服务 2. 负载均衡,并行多个key进行计算合并结果(mget) Tair的使用场景 缓存 分布式锁 作为nosql数据库,提供简单类型存储(K/V存储,无复杂查询) Tair使用QA 1. Q:tair的分布式锁使用有什么最佳实践? A:分布式锁使用建议使用带有过期时间的分布式锁,过期时间可传一个绝对的时间戳。解锁时可传入一个非常大的整数,以解掉所有的锁。
1、memcached分布式简介 memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。 根据上图我们简述分析分布式memcached的set与get的过程 set过程: 1、首先通过应用程序set(‘key’,’value’) 2、进入程序,使用key通过逻辑算法得出这个key需要存储的节点位置 2、取模算法方式 何为取模算法方式分布式?就是将key转换为32位的数字,并与memcached服务器的总数进行相除取得余数。而这个余数就是memcached服务器的节点node。 php 2 #分布式memcache(取模计算) 3 class GetModMemcache 4 { 5 private $total=''; #存储memcache 2、当需要扩容的时候,增加多台memcached服务器,那么原来已经缓存的数据大多数都不能够被命中,即数据无用。 3、一致哈希算法方式 何为一致哈希算法方式分布式呢?
一 分布式缓存特性 1) 高性能:当传统数据库面临大规模数据访问时,磁盘I/O 往往成为性能瓶颈,从而导致过高的响应延迟.分布式缓存将高速内存作为数据对象的存储介质,数据以key/value 形式存储, 二 典型应用场景 分布式缓存的典型应用场景可分为以下几类: 1) 页面缓存.用来缓存Web 页面的内容片段,包括HTML、CSS 和图片等,多应用于社交网站等; 2) 应用对象缓存.缓存系统作为ORM 三 缓存的分类 1) 本机缓存:数据存储在应用代码所在内存空间.优点是可以提供快速的数据访问;缺点是数据无法分布式共享,无容错处理 2) 分布式缓存系统:数据在固定数目的集群节点间分布存储.优点是缓存容量静态扩展 4) 弹性分布式缓存应用平台:弹性应用平台代表了云环境下分布式缓存系统未来的发展方向.简单地讲,弹性应用平台是弹性缓存与代码执行的组合体,将业务逻辑代码转移到数据所在节点执行,可以极大地降低数据传输开销 ,提升系统性能 也就是本地-分布式缓存中间件-动态分布式缓存中间件-在本机实现动态分布式缓存中间件
前言 目前工作中用到的分布式缓存技术有redis和memcached两种,缓存的目的是为了在高并发系统中有效降低DB的压力,但是在使用的时候可能会因为缓存结构设计不当造成一些问题,这里会把可能遇到的坑整理出来 2. 2. 回源方法内追加分布式锁:这个可以完全避免上面多实例下并发回源的情况,但是缺点也很明显,那就是又引入了一个新的服务,这意味着发生异常的风险会加大。 九. 缓存雪崩 1. 什么是缓存雪崩? 缓存服务宕机:某一时刻缓存服务器出现大量宕机的情况,导致缓存服务不可用,根据现有的实现,是直接打到DB上的。 2. 如何避免雪崩的发生?
分布式缓存:与应用分离的缓存组件,可以认为是独立的服务,和应用分开,多个应用之间可以共享,但是会存在网络请求。 5 分布式缓存设计可能需要考虑的几个问题站在巨人(Redis)的肩膀上, 我们可以学到很多优秀的设计、理念,设计一个功能比较全面的分布式缓存,到底需要考虑哪些问题? 5.2 2、内存不足怎么办?(缓存淘汰策略)单机内存不足,可以删除一些数据。但是到底删除哪些数据,这必须有一个决策的算法,这就是缓存淘汰策略。 6 使用分布式缓存可能会遇到的几个问题6.1 1、一致性问题如何保证缓存和数据库的一致性问题,是一个比较大的话题,我们除了保证数据库和缓存一致,分布式缓存的 master 和 slave 也需要保持一致 2、先更新数据库,再更新缓存- 在两个线程一起更新的场景下,如果先更新数据库的线程由于执行慢了一些,后更新缓存,很容易出现一致性问题。
score进行排序就可以得到坐标附近的其它元素,通过将score还原成坐标值就可以得到元素的原始坐标 HyperLogLog:统计不重复数据,用于大数据基数统计 Streams:内存版的kafka 数据库实现分布式锁的问题及解决方案 不可重入,如果加锁的方法需要递归,则第二次插入会失败,可以使用记录线程标识解决重入问题 死锁,删除锁失败、则其他线程没办法获取锁,可以设置超时时间、使用定时任务检查 数据库单点故障,数据库高可用 Redis分布式锁实现 异步复制可能造成锁丢失,使用redLock解决 顺序向五个节点请求加锁 根据一定的超时时间来推断是不是跳过该节点 三个节点加锁成功并且花费时间小于锁的有效期 认定加锁成功 往期精彩系列推荐 对线面试官系列 分布式基础概念系列
score进行排序就可以得到坐标附近的其它元素,通过将score还原成坐标值就可以得到元素的原始坐标HyperLogLog:统计不重复数据,用于大数据基数统计Streams:内存版的kafka数据库实现分布式锁的问题及解决方案利用唯一约束键存储 直到获取锁不可重入,如果加锁的方法需要递归,则第二次插入会失败,可以使用记录线程标识解决重入问题死锁,删除锁失败、则其他线程没办法获取锁,可以设置超时时间、使用定时任务检查数据库单点故障,数据库高可用Redis分布式锁实现 ,计数)异步复制可能造成锁丢失,使用redLock解决顺序向五个节点请求加锁根据一定的超时时间来推断是不是跳过该节点三个节点加锁成功并且花费时间小于锁的有效期认定加锁成功往期精彩系列推荐对线面试官系列分布式基础概念系列我正在参与
分布式缓存寻址算法 hash算法: 根据key进行hash函数运算、结果对分片数取模,确定分片适合固定分片数的场景。 哨兵用于实现redis集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。 故障转移时,判断一个master node是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的 哨兵通常需要3个实例,来保证自己的健壮性。 Javaredis客户端驱动jedis,支持Redis Sharding功能,即ShardedJedis以及结合缓存池的ShardedJedisPool 优点: 优势在于非常简单,服务端的Redis实例彼此独立 连接不能共享,当应用规模增大时,资源浪费制约优化 也可参考对线面试官系列文章: 对线面试官 Redis | 十 Redis集群模式 往期精彩内容推荐 分布式基础概念系列 对线面试官系列
分布式缓存寻址算法hash算法:根据key进行hash函数运算、结果对分片数取模,确定分片适合固定分片数的场景。 哨兵用于实现redis集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。 故障转移时,判断一个master node是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的哨兵通常需要3个实例,来保证自己的健壮性。 Javaredis客户端驱动jedis,支持Redis Sharding功能,即ShardedJedis以及结合缓存池的ShardedJedisPool优点:优势在于非常简单,服务端的Redis实例彼此独立 连接不能共享,当应用规模增大时,资源浪费制约优化也可参考对线面试官系列文章:https://mp.weixin.qq.com/s/2HoOd_d6tLFWQi1BpopSyw我正在参与2023腾讯技术创作特训营第三期有奖征文
如何避免缓存穿透、缓存击穿、缓存雪崩?缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。 缓存雪崩解决方案:缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失效,则更新数据缓存。 和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。缓存击穿解决方案设置热点数据永远不过期。加互斥锁分布式系统中常用的缓存方案有哪些? 客户端缓存:页面和浏览器缓存,APP缓存,H5缓存,localStorage和sessionStorageCDN缓存:内容存储:数据的缓存,内容分发:负载均衡nginx缓存:静态资源服务端缓存:本地缓存 ,外部缓存数据库缓存:持久层缓存(mybatis,hibernate多级缓存),mysql查询缓存操作系统缓存:Page Cache、Buffer Cache如何保证数据库与缓存的一致性?
这是直接读取数据库的数据 array(10) { [0] => array(12) { ["id"] => string(1) "1" ["catid"] => string(2) ["ord"] => string(1) "2" ["hits"] => string(1) "1" ["status"] => string(1) "1" } 第二次访问 array(10) { [0] => array(12) { ["id"] => string(1) "1" ["catid"] => string(2) "13 "] => string(1) "2" ["hits"] => string(1) "1" ["status"] => string(1) "1" } 说明:第一次运行时 ('静态规则', '有效期', '附加规则'), // 定义格式2 字符串方式 '静态地址' => '静态规则', ) 定义格式1采用数组方式 便于单独为某个静态规则设置不同的有效期,定义格式2