文章目录
5-1 本章目标
- 掌握多级缓存的定义
- 掌握redis缓存,本地缓存
- 掌握热点nginx lua缓存
5-2 缓存设计原则概览
缓存设计原则:
- 用快速存取设备,用内存
- 将缓存推到离用户最近的地方
- 脏缓存清理
我们的项目采用多级缓存的架构
- 第一级 Redis缓存
Redis缓存有集中管理缓存的特点,是常见NoSql数据库组件
- 第二级 热点缓存本地缓存
热点数据存到JVM本地缓存中
- 第三级 nginx proxy cache缓存
所有数据最后都会在nginx服务器上做反向代理,nginx服务器也可以开启proxy cache缓存
- 第四级 nginx lua缓存
nginx定制lua脚本做nginx内存缓存
5-3 Redis集中式缓存介绍
Redis是一个NoSql 基于Key-valule数据库的中间件,是易失的
Redis缓存的几种形式:
- 单机版:单个redis,目前项目就采用这种设计
**优点:**架构简单,方便,高性能
**缺点:**缓存中使用,重启后会丢失,数据丢失,即使有备用的节点解决高可用性,但是仍然不能解决缓存预热问题,因此不适用于数据可靠性要求高的业务+受CPU处理能力限制,CPU性能有瓶颈
1. Redis sentinal哨兵模式
Sentinel(哨兵)是用于监控redis集群中Master状态的工具,是Redis 的高可用性解决方案,sentinel哨兵模式已经被集成在redis2.4之后的版本中。
sentinel系统可以监视一个或者多个redis master服务,以及这些master服务的所有从服务;当某个master服务下线时,自动将该master下的某个从服务升级为master服务替代已下线的master服务继续处理请求
sentinel可以让redis实现主从复制,当一个集群中的master失效之后,sentinel可以选举出一个新的master用于自动接替master的工作,集群中的其他redis服务器自动指向新的master同步数据。一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换。其结构如下:
Redis支持主从同步机制,redis2作为redis1的slave从机,同步复制master的内容,当其中一个数据库宕机,应用服务器是很难直接通过找地址来切换成redis2,这时就用到了redis sentinal 哨兵机制。sentinal与redis1和redis2建立长连接,与主机连接是心跳机制,miaosha.jar无需知道redis1,redis2主从关系,只需ask
redis sentinal,之后sentinal就response
回应redis1为master,redis2为slave
一旦发生redis1坏掉或者发生网络异常,心跳机制就会破坏掉,sentinal更改redis2为master,redis1为slave,变换主从关系,然后发送change给应用服务器,然后miaosha.jar就向redis2进行get、set操作(或者redis读写分离,在master上set,slave上get)——redis 哨兵机制
总结一下:
Sentinal作用:
- Master状态检测
- 如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
2.Redis集群cluster模式
一般情况下,使用主从模式加Sentinal监控就可以满足基本需求了,但是当数据量过大一个主机放不下的时候,就需要对数据进行分区,将key按照一定的规则进行计算,并将key对应的value分配到指定的Redis实例上,这样的模式简称Redis集群。
cluster集群配置有多个slave用来读,master用来写,各种redis服务器彼此知道相互关系。
cluster好处:
- 将数据自动切分到多个节点
- 当集群某台设备故障时,仍然可以处理请求
- 节点的fail是集群中超过半数的节点检测失效时才生效
cluster故障转移
1. 节点故障判断
首先,在Redis Cluster中每个节点都存有集群中所有节点的信息。它们之间通过互相ping-pong判断节点是否可以连接。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机。
2.slave选举
当主节点被集群公认为fail状态,那么它的从节点就会发起竞选,如果存在多个从节点,数据越新的节点越有可能发起竞选。集群中其他主节点返回响应信息。
3.结构变更
当竞选从节点收到过半主节点同意,便会成为新的主节点。此时会以最新的Epoch通过PONG消息广播,让Redis Cluster的其他节点尽快的更新集群信息。当原主节点恢复加入后会降级为从节点。
Redis cluster 高可用性
1. 主节点保护
当集群中某节点中的所有从实例宕机时,Redis Cluster会将其他节点的非唯一从实例进行副本迁移,成为此节点的从实例。
这样集群中每个主节点至少有一个slave,使得Cluster 具有高可用。集群中只需要保持 2*master+1 个节点,就可以保持任一节点宕机时,故障转移后继续高可用。
2. 集群fail条件
Redis Cluster保证基本可用的特性,在达到一定条件时才会认定为fail:
1、某个主节点和所有从节点全部挂掉,则集群进入fail状态。
2、如果集群超过半数以上主节点挂掉,无论是否有从节点,集群进入fail状态。
3、如果集群任意主节点挂掉,且当前主节点没有从节点,集群进入fail状态。
5-4 Redis集中式缓存商品详情页接入
在商品详情页添加redis缓存
ItemController:
//商品详情页浏览
@RequestMapping(value = "/get",method = RequestMethod.GET) //浏览时服务端用GET请求
@ResponseBody
public CommonReturnType getItem(@RequestParam(name = "id") Integer id) {
//根据商品的id到redis内获取
ItemModel itemModel = (ItemModel) redisTemplate.opsForValue().get("item_"+id);
//若redis内不存在对应的itemModel,则访问下游service
if(itemModel == null) {
itemModel = itemService.getItemById(id);
//设置itemModel到redis内
redisTemplate.opsForValue().set("item_"+id,itemModel);
redisTemplate.expire("item_"+id,10, TimeUnit.MINUTES);
}
ItemVO itemVO = this.convertVOFromModel(itemModel);
return CommonReturnType.create(itemVO);
}
ItemModel、PromoModel要实现序列化
查看Redis写入的数据,发现会出现如下乱码:
修改config文件夹下的RedisConfig
@Component
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
//首先解决key的序列化方式
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
//解决value的序列化方式
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class)