什么场景下会使用到缓存?

1.数据库缓存,减轻数据库服务器压力

一般情况下数据存在数据库中,应用程序直接操作数据库。当访问量上万,10万、百万,需要引入缓存。

将已经访问过的内容或数据存储起来,当再次访问时先找缓存,缓存命中返回数据。不命中再找数据库,并回填缓存。

2.提高系统响应

数据库的数据是存在文件里,也就是硬盘。与内存做交换(swap)

将数据缓存在Redis中,也就是存在了内存中。内存天然支持高并发访问。可以瞬间处理大量请求。qps到达11万/S读请求 8万/S 写请求。

3.做Session分离

传统的session是由tomcat自己进行维护和管理。集群或分布式环境,不同的tomcat管理各自的session。

只能在各个tomcat之间,通过网络和Io进行session的复制,极大的影响了系统的性能。

将登录成功后的Session信息,存放在Redis中,这样多个服务器(Tomcat)可以共享Session信息。Redis的作用是数据的临时存储

redis缓存架构方案 redis缓存实现思路_缓存

4.做分布式锁(Redis)

一般讲锁是多线程的锁,是在一个进程中的,多个进程(JVM)在并发时也会产生问题,也要控制时序性,可以采用分布式锁。可以通过Redis的 setNX 实现

做乐观锁(Redis)

同步锁和数据库中的行锁、表锁都是悲观锁,悲观锁的性能是比较低的,响应性比较差高性能、高响应(秒杀)采用Redis可以实现乐观锁 watch + incr


理解缓存原理 常见缓存类型

学习缓存原理之前先了解什么是缓存?

缓存原指CPU上的一种高速存储器,它先于内存与CPU交换数据,速度很快。现在泛指:存储在计算机上的原始数据的复制集,便于快速访问。

在互联网技术中,缓存是系统快速响应的关键技术之一,以空间换时间的一种技术(艺术)

在大型网站中从浏览器到网络,再到应用服务器,再到数据库,通过在各个层面应用缓存技术,大大提升了系统性能和用户体验。

常见的缓存类型?可以分为: 客户端缓存 服务端缓存

redis缓存架构方案 redis缓存实现思路_redis缓存架构方案_02

客户端缓存如: 页面缓存 浏览器缓存 app缓存

网络端缓存如:web 代理缓存 (比如Nginx) 边缘缓存 如CDN

服务端缓存如:

  • 数据库级缓存(mysql 在server层使用查询缓存机制 innodb 存储引擎中的buffer-pool用于缓存innodb索引以及数据块)
  • 平台级缓存 (指定是带有缓存特性的应用框架,比如 GuavaCache 等,部署在应用服务器上也称为服务器本地缓存)
  • 应用级缓存 (具有缓存功能的中间件产品)如redis Tair Memcached等,采用k/v键值对进行存储,利用集群支持高可用 高性能 高并发 高扩展 等特性

了解缓存的优势和代价

优势:

  • 提升用户体验
  • 用户体验(User Experience):用户在使用产品过程中建立起来的一种纯主观感受。缓存的使用可以提升系统的响应能力,大大提升了用户体验。
  • 减轻服务器压力
  • 客户端缓存、网络端缓存减轻应用服务器压力。服务端缓存减轻数据库服务器的压力。
  • 提升系统性能
  • 系统性能指标:响应时间、延迟时间、吞吐量、并发用户数和资源利用率等。

代价:

  • 额外的硬件支出
  • 缓存是一种软件系统中以空间换时间的技术,需要额外的磁盘空间和内存空间来存储数据,搭建缓存服务器集群需要额外的服务器 采用云服务器的缓存服务就不用额外的服务器了阿里云(Tair、Redis),百度云(Redis),提供缓存服务AWS亚马逊云服务:EVCache
  • 高并发缓存失效
  • 在高并发场景下会出现缓存失效(缓存穿透、缓存雪崩、缓存击穿)造成瞬间数据库访问量增大,甚至崩溃
  • 缓存与数据库数据同步问题:导致数据不一致
  • 缓存与数据库无法做到数据的时时同步,Redis无法做到主从时时数据同步
  • 缓存并发竞争
  • 多个redis的客户端同时对一个key进行set值得时候由于执行顺序引起的并发问题

理解Redis缓存的读写模式

缓存经常采用的读写模式有三种:

Cache Aside Pattern(旁路缓存):是最经典的 缓存+数据库读写模式。

读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。

redis缓存架构方案 redis缓存实现思路_redis_03

更新的时候: 先更新数据库的值,然后删除缓存

redis缓存架构方案 redis缓存实现思路_数据_04

 为什么是删除缓存,而不是更新缓存呢?

1、缓存的值是一个结构:hash、list,更新数据需要遍历,先遍历(耗时)后修改

更新思路:

懒加载,使用的时候才更新缓存, 使用的时候才从DB中加载

也可以采用异步的方式填充缓存, 开启一个线程 定时将DB的数据刷到缓存中

高并发脏读的情况

1、先更新数据库,再更新缓存

update与commit之间,更新缓存,commit失败 ,则DB与缓存数据不一致

2、先删除缓存,再更新数据库

update与commit之间,有新的读,缓存空,读DB数据到缓存 数据是旧的数据 ,commit后 DB为新数据 ,则DB与缓存数据不一致

3、先更新数据库,再删除缓存(推荐)

update与commit之间,有新的读,缓存空,读DB数据到缓存 数据是旧的数据,commit后 DB为新数据, 则DB与缓存数据不一致

采用延时双删策略Read/Write Through Pat

缓存的常见设计思路并能够运用到项目中

可结合秒杀系统进行分析

1.首先需要多层次设置缓存,比如先 负载均衡服务器缓存 前端页面缓存 服务端缓存 数据库缓存

2.根据存放的数据选择合适的服务器缓存,如:

简单数据类型: Value是字符串或整数或二进制 Value的值比较大(大于100K) 只进行setter和getter 可采用Memcached Memcached纯内存缓存,多线程 K-V

复杂数据类型: Value是hash、set、list、zset 需要存储关系,聚合,计算 可采用Redis

3.缓存服务器应该做成集群,原因是:保证高可用性

redis 集群可采用: codis 哨兵+主从 RedisCluster

4.缓存的数据结构设计

可根据实际需求,设计的数据表一致