3、查询性能优化技术之多级缓存

5.1本章目标

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缓存的几种形式:

1.单机版

单个redis,目前项目就采用这种设计
优点:架构简单,方便,高性能

缺点:缓存中使用,重启后会丢失,数据丢失,即使有备用的节点解决高可用性,但是仍然不能解决缓存预热问题,因此不适用于数据可靠性要求高的业务+受CPU处理能力限制,CPU性能有瓶颈

2.Redis sentinal哨兵模式

sentinel系统可以监视一个或者多个redis master服务,以及这些master服务的所有从服务;当某个master服务下线时,自动将该master下的某个从服务升级为master服务替代已下线的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

3.Redis集群cluster模式

但是当数据量过大一个主机放不下的时候,就需要对数据进行分区,将key按照一定的规则进行计算,并将key对应的value分配到指定的Redis实例上,这样的模式简称Redis集群。

cluster集群配置有多个slave用来读,多个master用来写,各种redis服务器彼此知道相互关系、也知道自己的主从关系。每个master管理不同的数据。

1. 节点故障判断

首先,在Redis Cluster中每个节点都存有集群中所有节点的信息。它们之间通过互相ping-pong判断节点是否可以连接。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机。

2.slave选举

当主节点被集群公认为fail状态,那么它的从节点就会发起竞选,如果存在多个从节点,数据越新的节点越有可能发起竞选。集群中其他主节点返回响应信息。

3.结构变更

当竞选从节点收到过半主节点同意,便会成为新的主节点。此时会以最新的Epoch通过PONG消息广播,让Redis Cluster的其他节点尽快的更新集群信息。当原主节点恢复加入后会降级为从节点。

在这里插入图片描述

cluster好处:
将数据自动切分到多个节点
当集群某台设备故障时,仍然可以处理请求
节点的fail是集群中超过半数的节点检测失效时才生效

5.4/5 Redis集中式缓存商品详情页接入

在商品详情页添加redis缓存

ItemController:

 //商品详情页浏览
    @RequestMapping(value = "/get", method = {
   RequestMethod.GET})
    @ResponseBody
    public CommonReturnType getItem(@RequestParam(name = "id")Integer id){
   
        ItemModel itemModel = null;

        //根据商品的id到redis中获取
        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);
            //redis缓存失效时间——十分钟,为了更好的节约空间和服务器负担
            redisTemplate.expire("item_"+id,10, TimeUnit.MINUTES);
        }

        ItemVO itemVO = convertVOFromModel(itemModel);

        return CommonReturnType.create(itemVO);
    }

与此同时,ItemModel、PromoModel要实现序列化,(implements Serializable)

这样可以实现使用网页端的redis进行十分钟内的暂时存取。

查看redis写入的数据:
在这里插入图片描述

flushall命令可以在redis中清除所有的key-value对

此时是因为序列化的时候没有使用的redis默认的序列化编码方式,所以为了能够让redis能够认清我们的定义,方便的debug,使用我们自己定义的序列化方式,打开并修改config文件夹下的RedisConfig,重写RedisTemplate

//加载这个bean
@Component
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
public class RedisConfig {
   
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值