【Java知识点1】缓存

目录

1、缓存能做什么?

2、预读取

3、延迟写

4、哪里可以加缓存?

5、缓存类别  

6、缓存引发的问题


1、缓存能做什么?

当遇到页面打开很慢的时候,会引入缓存,这样页面响应就会块很多。快慢是相对的,从技术的角度来源,缓存的数据之所以快,是因为缓存是基于内存建立的,而内存的读写速度比硬盘快很多倍,所以用内存代替磁盘作为读写的介质能大大提高访问数据的速度。

访问过程如下: 

 通过在内存中存储被访问的数据提供给程序使用,从此达到提速的目的。

 缓存有两个运用方式:预读取和延迟写。

  • 预读取是在数据出口加缓冲区。
  • 延迟写是在数据入口加缓冲区。

2、预读取

预读取就是先读取将要载入的数据,也称为“预存预热”,它是系统启动时先将硬盘中的一部分数据加载到内存中,供外部服务调用。如下图:

 优点:因为系统启动之后就要面临巨大的请求量时,如果直接让这些请求到达数据库上,数据库的压力暴增,数据库服务容易崩溃,无法正常响应。而预读取就会解决这个问题,降低数据库的压力。

3、延迟写

数据库写入速度慢于读取速度,因为写入的时候有一系列的数据准确性的机制。要想提升写入速度,要么分库分表,要么通过缓存缓冲,然后再批量写入磁盘。

由于分库分表对跨表操作以及多条件组合查询的副作用大,所以他的复杂度大于引入缓存。

通过缓存机制加速写的过程称为“延迟写”,它预先将需要写入磁盘或数据库的数据,先暂时写入内存,然后返回成功,再定时将内存中的数据批量写入磁盘。 

数据写缓存,有数据丢失的风险,所以延迟写一般仅用于对数据完整性要求不是很苛刻的场景,比如点赞数,参与用户数等,可以大大缓解对数据库的频繁修改所带来的压力。

在分布式缓存Redis中,其默认运用的持久化机制--RDB,就是这个思路。

4、哪里可以加缓存?

哪些数据需要添加到缓存?

两个标准衡量:

  • 热点数据:被高频访问
  • 静态数据:很少变化,读大于写

每个设立点可以挡掉一些流量,最终形成一个漏斗状的拦截效果,以此保护最后面的系统以及最终的数据库

5、缓存类别  

  •  浏览器缓存

        数据被缓存在用户的浏览上,一般用于缓存图片,js与css这些资源,可以通过http消息头中的Cache-Control来控制它。

        缺点:浏览器缓存是在用户端的缓存点,我们对它的控制力比较差,

  •  CDN缓存

        将数据分发到CDN服务的服务商在各个地方提供的服务器上作为缓存,让用户访问就近的服务器上的缓存数据,就起到了压力分摊和页面访问加速效果。

        缺点:节点众多,更新缓存数据比较慢,一般是分钟级别,所以一般适用不经常变动的静态数据。

  •  网关缓存

        在源站前面加一层网关,为的是加强安全机制或则统一分流策略的入口。

        

        网关也可以作为缓存使用,网关与业务无关,它能够拦截请求,对背后的源站资源也有很大的受益,减少大量的CPU运算。 

        常用的网关缓存有Varnish、Squid与Ngnix。一般情况下,简单的缓存运用场景,用Ngnix即可,因为大部分时候我们会用它做负载均衡,能少引入一个技术就少一分复杂度。如果是大量的小文件可以使用Varnish,而 Squid 则相对大而全,运用成本也更高一些。

  •  进程内缓存

        进程内使用缓存是一个比较常见的场景。

        一个请求到了这里说明它是和业务相关的,需要经过业务逻辑处理的。因此,这里使用缓存的成本大于前的3种,因为对缓存数据和数据库中的数据的一致性要求更高。

  •  进程外缓存

        进程外缓存是使用第三方工具,redis,memcached等等之类。

Redis 和 Memcached 该怎么选择的思路

对资源(CPU、内存等)利用率格外重视的话可以使用Memcached ,但程序在使用的时候需要容忍可能发生的数据丢失,因为纯内存的机制。如果无法容忍这单,并对资源利用率也比较豪放的话就可以使用Redis。而且Redis的数据库结构更多, Memcached 只有 key-value,更像是一个 NoSQL 存储。

  •  数据库缓存

        数据库缓存是数据库内部机制,一般都会设置缓存空间大小。

6、缓存引发的问题

1、缓存雪崩

        大量的请求并发进入时,由于某些原因未起到预期的缓存效果,在很短的时间内,导致请求全部转移到数据库,造成数据库压力过大,数据库崩溃。

        解决方案:通过“加锁排队”或者“缓存过期时间增加随机值”

2、缓存穿透

        和缓存雪崩类似,区别是持续更长时间,因为每次“cache miss”后,依然无法从数据源加载数据到缓存,导致持续产生“cache miss”

        解决方法:通过“布隆过滤器”或者“缓存空对象”

3、缓存并发

        一个缓存key下的数据被同时set,怎么保证业务的准确性?再加上数据库的话?进程内缓存、进程外缓存与数据库三者皆用的情况下呢?

        解决方法:使用“先DB再缓存”的方式,并且缓存操作使用delete而不是set

4、缓存无底洞

        分布式缓存是可以无限横向扩展,不是节点越多越好

        解决方案:缓存符合“边际效用递减”

5、缓存淘汰

        内存总是有限的,如果数据量很大,那么根据具体的场景定制合理的淘汰策略是必不可少的, 如 LRU、LFU 与 FIFO 等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值