- 浏览: 599217 次
- 性别:
- 来自: 厦门
文章分类
- 全部博客 (669)
- oracle (36)
- java (98)
- spring (48)
- UML (2)
- hibernate (10)
- tomcat (7)
- 高性能 (11)
- mysql (25)
- sql (19)
- web (42)
- 数据库设计 (4)
- Nio (6)
- Netty (8)
- Excel (3)
- File (4)
- AOP (1)
- Jetty (1)
- Log4J (4)
- 链表 (1)
- Spring Junit4 (3)
- Autowired Resource (0)
- Jackson (1)
- Javascript (58)
- Spring Cache (2)
- Spring - CXF (2)
- Spring Inject (2)
- 汉字拼音 (3)
- 代理模式 (3)
- Spring事务 (4)
- ActiveMQ (6)
- XML (3)
- Cglib (2)
- Activiti (15)
- 附件问题 (1)
- javaMail (1)
- Thread (19)
- 算法 (6)
- 正则表达式 (3)
- 国际化 (2)
- Json (3)
- EJB (3)
- Struts2 (1)
- Maven (7)
- Mybatis (7)
- Redis (8)
- DWR (1)
- Lucene (2)
- Linux (73)
- 杂谈 (2)
- CSS (13)
- Linux服务篇 (3)
- Kettle (9)
- android (81)
- protocol (2)
- EasyUI (6)
- nginx (2)
- zookeeper (6)
- Hadoop (41)
- cache (7)
- shiro (3)
- HBase (12)
- Hive (8)
- Spark (15)
- Scala (16)
- YARN (3)
- Kafka (5)
- Sqoop (2)
- Pig (3)
- Vue (6)
- sprint boot (19)
- dubbo (2)
- mongodb (2)
最新评论
缓存穿透与并发方案
相信不少朋友之前看过很多类似的文章,但是归根结底就是二个问题:
1.如何解决穿透
2.如何解决并发
当并发较高的时候,其实我是不建议使用缓存过期这个策略的,我更希望缓存一直存在,通过后台系统来更新缓存系统中的数据达到数据的一致性目的,有的朋友可能会质疑,如果缓存系统挂了怎么办,这样数据库更新了但是缓存没有更新,没有达到一致性的状态。
解决问题的思路是如果缓存是因为网络问题没有更新成功数据,那么建议重试几次,如果依然没有更新成功则认为缓存系统出错不可用,这时候客户端会将数据的KEY插入到消息系统中,消息系统可以过滤相同的KEY,只需保证消息系统不存在相同的KEY,当缓存系统恢复可用的时候,依次从MQ中取出KEY值然后从数据库中读取最新的数据更新缓存。
注意:更新缓存之前,缓存中依然有旧数据,所以不会造成缓存穿透。
下图展示了整个思路的过程:
看完上面的方案以后,又会有不少朋友提出疑问,如果我是第一次使用缓存或者缓存中暂时没有我需要的数据,那又该如何处理呢?
在这种场景下,客户端从缓存中根据KEY读取数据,如果读到了数据则流程结束,如果没有读到数据(可能会有多个并发都没有读到数据),这时候使用缓存系统中的setNX方法设置一个值(这种方法类似加个锁),没有设置成功的请求则sleep一段时间,设置成功的请求读取数据库获取值,如果获取到则更新缓存,流程结束,之前sleep的请求这时候唤醒后直接再从缓存中读取数据,此时流程结束。
在看完这个流程后,我想这里面会有一个漏洞,如果数据库中没有我们需要的数据该怎么处理,如果不处理则请求会造成死循环,不断的在缓存和数据库中查询,这时候我们会沿用我之前文章中的如果没有读到数据则往缓存中插入一个NULL字符串的思路,这样其他请求直接就可以根据“NULL”进行处理,直到后台系统在数据库成功插入数据后同步更新清理NULL数据和更新缓存。
流程图如下所示:
在实际工作中,我们往往将上面二个方案组合使用才能达到最佳效果,虽然第二种方案也会造成请求阻塞,但是只是在第一次使用或者缓存暂时没有数据的情况下才会产生,在生产中经过检验在TPS没有上万的情况下是不会造成问题的。
热点缓存解决方案
1. 缓存使用背景:
我们拿用户中心的一个案例来说明。每个用户都会首先获取自己的用户信息,然后再进行其他相关的操作,有可能会有如下一些场景情况:
会有大量相同用户重复访问该项目。
会有同一用户频繁访问同一模块。
2. 思路解析
因为用户本身是不固定的而且用户数量也有几百万尤其上千万,我们不可能把所有的用户信息全部缓存起来,通过第一个场景情况可以看到一些规律,那就是有大量的相同用户重复访问,但是究竟是哪些用户重复访问我们也并不知道。
如果有一个用户频繁刷新读取项目,那么对数据库本身也会造成较大压力,当然我们也会有相关的保护机制来确实恶意攻击,可以从前端控制,也可以有采黑名单等机制,这里不在赘述。如果用缓存的话,我们又该如何控制同一用户繁重读取用户信息呢。
我们会通过缓存系统做一个排序队列,比如1000个用户,系统会根据用户的访问时间更新用户信息的时间,越是最近访问的用户排名越排前,系统会定期过滤掉排名最后的200个用户,然后再从数据库中随机取出200个用户加入队列,这样请求每次到达的时候,会先从队列中获取用户信息,如果命中则根据userId,再从另一个缓存数据结构中读取用户信息,如果没有命中则说明该用户请求频率不高。
转自:http://mp.weixin.qq.com/s?__biz=MzA5Nzc4OTA1Mw==&mid=2659599137&idx=1&sn=4aa0bfb8df43dfc6c5c3bd59baa00a77&chksm=8be99633bc9e1f2564ddc1b45f723846025e98bb62f134ac403696601128550ec79536dcfe04&mpshare=1&scene=23&srcid=0411YpVMJsgoqHBkpSWQuDNB#rd
相信不少朋友之前看过很多类似的文章,但是归根结底就是二个问题:
1.如何解决穿透
2.如何解决并发
当并发较高的时候,其实我是不建议使用缓存过期这个策略的,我更希望缓存一直存在,通过后台系统来更新缓存系统中的数据达到数据的一致性目的,有的朋友可能会质疑,如果缓存系统挂了怎么办,这样数据库更新了但是缓存没有更新,没有达到一致性的状态。
解决问题的思路是如果缓存是因为网络问题没有更新成功数据,那么建议重试几次,如果依然没有更新成功则认为缓存系统出错不可用,这时候客户端会将数据的KEY插入到消息系统中,消息系统可以过滤相同的KEY,只需保证消息系统不存在相同的KEY,当缓存系统恢复可用的时候,依次从MQ中取出KEY值然后从数据库中读取最新的数据更新缓存。
注意:更新缓存之前,缓存中依然有旧数据,所以不会造成缓存穿透。
下图展示了整个思路的过程:
看完上面的方案以后,又会有不少朋友提出疑问,如果我是第一次使用缓存或者缓存中暂时没有我需要的数据,那又该如何处理呢?
在这种场景下,客户端从缓存中根据KEY读取数据,如果读到了数据则流程结束,如果没有读到数据(可能会有多个并发都没有读到数据),这时候使用缓存系统中的setNX方法设置一个值(这种方法类似加个锁),没有设置成功的请求则sleep一段时间,设置成功的请求读取数据库获取值,如果获取到则更新缓存,流程结束,之前sleep的请求这时候唤醒后直接再从缓存中读取数据,此时流程结束。
在看完这个流程后,我想这里面会有一个漏洞,如果数据库中没有我们需要的数据该怎么处理,如果不处理则请求会造成死循环,不断的在缓存和数据库中查询,这时候我们会沿用我之前文章中的如果没有读到数据则往缓存中插入一个NULL字符串的思路,这样其他请求直接就可以根据“NULL”进行处理,直到后台系统在数据库成功插入数据后同步更新清理NULL数据和更新缓存。
流程图如下所示:
在实际工作中,我们往往将上面二个方案组合使用才能达到最佳效果,虽然第二种方案也会造成请求阻塞,但是只是在第一次使用或者缓存暂时没有数据的情况下才会产生,在生产中经过检验在TPS没有上万的情况下是不会造成问题的。
热点缓存解决方案
1. 缓存使用背景:
我们拿用户中心的一个案例来说明。每个用户都会首先获取自己的用户信息,然后再进行其他相关的操作,有可能会有如下一些场景情况:
会有大量相同用户重复访问该项目。
会有同一用户频繁访问同一模块。
2. 思路解析
因为用户本身是不固定的而且用户数量也有几百万尤其上千万,我们不可能把所有的用户信息全部缓存起来,通过第一个场景情况可以看到一些规律,那就是有大量的相同用户重复访问,但是究竟是哪些用户重复访问我们也并不知道。
如果有一个用户频繁刷新读取项目,那么对数据库本身也会造成较大压力,当然我们也会有相关的保护机制来确实恶意攻击,可以从前端控制,也可以有采黑名单等机制,这里不在赘述。如果用缓存的话,我们又该如何控制同一用户繁重读取用户信息呢。
我们会通过缓存系统做一个排序队列,比如1000个用户,系统会根据用户的访问时间更新用户信息的时间,越是最近访问的用户排名越排前,系统会定期过滤掉排名最后的200个用户,然后再从数据库中随机取出200个用户加入队列,这样请求每次到达的时候,会先从队列中获取用户信息,如果命中则根据userId,再从另一个缓存数据结构中读取用户信息,如果没有命中则说明该用户请求频率不高。
转自:http://mp.weixin.qq.com/s?__biz=MzA5Nzc4OTA1Mw==&mid=2659599137&idx=1&sn=4aa0bfb8df43dfc6c5c3bd59baa00a77&chksm=8be99633bc9e1f2564ddc1b45f723846025e98bb62f134ac403696601128550ec79536dcfe04&mpshare=1&scene=23&srcid=0411YpVMJsgoqHBkpSWQuDNB#rd
发表评论
文章已被作者锁定,不允许评论。
-
html pre标签使用(保留空格和回车等操作)
2018-05-15 08:37 2441pre 元素可定义预格式化的文本。被包围在 pre 元素中的文 ... -
java RESTful 详解
2018-04-27 11:35 643(1)每一个URI代表一种资源,独一无二; (2)客户端 ... -
缓存穿透(预设值防止多个进程读取数据库)、缓存并发、缓存失效(过期时间用随机数)学习
2018-02-22 14:25 433一、缓存穿透 我们在项 ... -
web http协议学习
2017-11-15 15:15 514HTTP协议是web开发必须掌握的协议之一,文章的内容并没有按 ... -
spring boot进行mybatis和JPA的整合
2017-08-30 10:12 4683初识spring boot Spring框架功能很强大,但是就 ... -
java CyclicBarrier进行并发编程
2017-08-25 15:44 673CyclicBarrier允许一组线程相互等待达到一个公共的障 ... -
java 几种性能优化的总结
2017-08-23 14:08 3251、使用StringBuilder 一般 ... -
java 使用kyro进行高性能序列化对象和集合
2017-08-23 14:05 2152import java.io.ByteArrayInp ... -
java 对重复电话号码进行排除的优化(排序和前后对比)
2017-08-22 14:14 7901.先对10万数据排序; 2.对比前后两条数据 ; 3.筛 ... -
系统架构设计理论与原则、负载均衡及高可用系统设计速记
2017-02-14 15:14 487一、系统架构设计理论与原则 这里主要介绍几种常见的架构设计理论 ... -
java Cookie操作总结
2017-02-04 09:14 474java对cookie的操作比较简单,主要介绍下建立cooki ... -
HTTP Cache机制学习(response meta标签)
2017-01-03 15:10 738HTTP Cache:response头部设置、http页面m ... -
java Statement和PreparedStatement的区别
2016-12-02 10:43 425第一 prepareStatement会先初始化SQL,先把这 ... -
java AbstractQueuedSynchronizer介绍以及原理分析
2016-11-18 14:27 505简介 提供了一个基于FIF ... -
java AtomicInteger基于CAS的乐观锁实现
2016-11-16 11:13 4691. 悲观锁与乐观锁 ... -
java Guava cache学习笔记
2016-11-15 18:26 731缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单 ... -
公钥、私钥和SSL详细说明(生动例子)
2016-11-11 08:43 576一,公钥私钥 1,公钥 ... -
spring ehcache配置以及使用(afterPropertiesSet)
2016-11-08 19:24 1360spring 配置ehcache例子:http://blog. ... -
java 各个连接池学习总结(DBCP C3P0 PROXOOL)
2016-11-08 19:00 1242要了解Java连接池我们先要了解数据库连接池(conne ... -
java 过滤器、监听器和拦截器区别
2016-11-08 10:21 416过滤器 Servlet中的过滤器Filter是实现了javax ...
相关推荐
解决缓存穿透的方法有以下几点: 1. **布隆过滤器**:使用布隆过滤器来存储可能存在的数据键,通过这个过滤器预先判断一个键是否存在,减少无效的数据库查询。 2. **设置空值缓存**:即使数据库中没有对应数据,也...
解决缓存穿透可使用布隆过滤器,将所有可能存在的数据哈希到一个位图中,无效的查询会被拦截;另一种简单方法是将空结果也缓存,但设置较短的过期时间。 3. **缓存预热** 缓存预热是在系统上线前或重启后,提前...
### Redis系统学习之缓存穿透、缓存击穿与缓存雪崩的概念及其...综上所述,缓存穿透、缓存击穿和缓存雪崩是常见的缓存问题,通过合理的架构设计和策略选择,可以有效地避免这些问题的发生,提高系统的稳定性和性能。
Redis缓存穿透、缓存雪崩、缓存击穿的原因和解决方案 ...缓存穿透、缓存雪崩、缓存击穿都是 Redis 缓存中需要注意的问题,了解它们的原因和解决方案,可以帮助我们更好地使用 Redis 缓存,提高系统的性能和可靠性。
综上所述,缓存穿透、缓存击穿和缓存雪崩是缓存技术中的三个常见问题,它们对系统的稳定性构成了巨大威胁。通过对业务层面的校验、采用布隆过滤器、引入互斥锁、设置合适的缓存过期策略,以及实时监控和优化,可以...
解决方案有很多种方法可以有效地解决缓存穿透问题。最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询...
Redis缓存穿透、缓存击穿、缓存雪崩面试题解析 Redis缓存穿透、缓存击穿...Redis缓存穿透、缓存击穿、缓存雪崩是Redis缓存机制中需要注意的问题,通过合理的解决方案可以避免这些问题的出现,提高系统的性能和稳定性。
### 常见的缓存穿透、缓存击穿、缓存雪崩解决...以上方案通过不同的技术手段有效地解决了缓存穿透、缓存击穿以及缓存雪崩等问题,提高了系统的稳定性和可靠性。在实际部署过程中,应根据具体情况选择最合适的解决方案。
### 缓存在高并发场景下的常见问题 #### 一、缓存一致性问题 在高并发环境下,缓存的一致性成为了一个重要的挑战。...通过对上述常见问题的理解和解决方法的应用,可以有效地提升系统的整体性能。
解决方案有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询...
解决缓存穿透的关键在于对请求数据的有效校验和对缓存的合理处理。首先,应对请求参数进行校验,过滤掉不合理的查询。其次,对于查询不到的数据,可以将它们缓存起来,并设置一个特殊的标记,这样可以有效避免相同的...
本文主要介绍了缓存系统中三个常见的问题:缓存穿透、缓存击穿和缓存雪崩,并对每个问题提供了多种解决方案。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,...
缓存穿透的解决方案 缓存穿透是一个常见的问题,在高并发的情况下,可能会导致数据库宕机。缓存穿透是指在缓存中没有查...解决缓存穿透的问题有多种方法,每种方法都有其特点和缺陷,需要根据业务场景选择合适的方法。
缓存是IT系统中常用的加速数据访问的工具,但如果不恰当设计和管理,可能会引发一些严重问题,如缓存穿透、缓存击穿和缓存雪崩。以下是对这三个问题的详细解释及其解决方案。 1. **缓存穿透** 缓存穿透是指请求的...
在IT领域,特别是针对高性能和高并发的应用场景中,缓存穿透是一种常见的问题。它指的是客户端请求的数据既不在缓存中也不在数据库中,但客户端仍频繁发起请求,试图获取该数据的情况。这种情况尤其容易被恶意攻击者...
图片资源“02_如何解决缓存雪崩.png”、“01_缓存雪崩现象.png”和“03_缓存穿透现象以及解决方案.png”可能会提供更加直观的示例,帮助理解这两种问题的场景和解决方案。而“PPT.pptx”可能是详细的讲解材料,包含...
### 缓存穿透及其解决方案 #### 缓存穿透定义 缓存穿透是指客户端请求的数据既不在缓存中也不在数据库中。这种情况会导致每次请求都需要穿透到数据库层,使得数据库承担额外的查询负担,可能导致数据库服务崩溃。 ...
总结来说,应对缓存问题,我们需要理解不同场景下的挑战,如缓存穿透带来的无效数据库查询、缓存雪崩造成的系统崩溃以及缓存击穿可能导致的数据库瞬间压力。通过合理的缓存设计,如使用布隆过滤器、设置空值缓存、...
然而,缓存系统在实际运行中可能会遇到几种常见问题,即缓存穿透、缓存击穿和缓存雪崩。下面将详细阐述这些问题以及相应的解决方案。 **缓存穿透** 缓存穿透是指用户请求的数据在缓存和数据库中均不存在,通常是...