首页 > 数据库 >redis-3

redis-3

时间:2024-12-29 19:10:18浏览次数:1  
标签:缓存 redis 192.168 connection key import

缓存流程图

缓存实战
准备工作
复制项目,修改名称
引入jar包

<!--springboot整合redis jar  开始-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<!--springboot整合redis jar  结束-->

编写Cache接口的实现类

package com.aaa.sbm.util;

import io.swagger.models.auth.In;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @FileName: MyCustomCache
 * @Description:
 * @Author: zhz
 * @CreateTime: 2024/12/4 11:53
 * @Version: 1.0.0
 */
//@Component
public class MyCustomCache implements Cache {
    //缓存对象的唯一id
    private String  id;

    //ReentrantReadWriteLock 可重入的读写锁    redis缓存的对象的读写策略     读读共享  读写互斥  写读互斥  写写互斥
    private static  ReadWriteLock readWriteLock =new ReentrantReadWriteLock();

    //jedis连接redis的工厂类  创建一个一个的连接
    //@Resource
    private static JedisConnectionFactory jedisConnectionFactory;

    /**
     * 配置一个静态注入方法
     * @param jedisConnectionFactory
     */
    public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        MyCustomCache.jedisConnectionFactory = jedisConnectionFactory;
    }

    public MyCustomCache() {
    }

    /**
     * //type 属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口,
     *     // 且提供一个接受 String 参数作为 id 的构造器。
     * @param id
     */
    public MyCustomCache(String id) {
        //判断是否为null
        if(StringUtils.isEmpty(id)){
            //如果null就抛出异常
            throw  new IllegalArgumentException("id不能为null!");
        }
        this.id = id;
    }

    /**
     * 返回当前缓存对象的唯一识别
     * @return
     */
    @Override
    public String getId() {
        return this.id;
    }

    /**
     * 添加缓存
     * @param key
     * @param value
     */
    @Override
    public void putObject(Object key, Object value) {
        //使用工厂创建redis链接对象
        RedisConnection connection = jedisConnectionFactory.getConnection();
        //序列化key和value
          //1,实例化序列化和反序列对象
        JdkSerializationRedisSerializer  jdkSerializationRedisSerializer =new JdkSerializationRedisSerializer();
          //2,序列化KV
        byte[] serializeKey = jdkSerializationRedisSerializer.serialize(key);
        byte[] serializeValue = jdkSerializationRedisSerializer.serialize(value);
        //要求存入的序列化过的key和value
        connection.set(serializeKey,serializeValue);
        //不要执行关闭,因为我要提高效率,使用redis连接池技术 ,连接池会自己管理链接,所以不用自行关闭
        //connection.close();
    }

    /**
     * 根据key获取缓存
     * @param key
     * @return
     */
    @Override
    public Object getObject(Object key) {
        //使用工厂创建redis链接对象
        RedisConnection connection = jedisConnectionFactory.getConnection();
        //序列化key和value
        //1,实例化序列化和反序列对象
        JdkSerializationRedisSerializer  jdkSerializationRedisSerializer =new JdkSerializationRedisSerializer();
        //2,序列化K
        byte[] serializeKey = jdkSerializationRedisSerializer.serialize(key);
        //3,根据序列化的key获取到序列化的值
        byte[] serializeValue = connection.get(serializeKey);
        //4,反序列化,把字节数组变回对象  并返回
        return jdkSerializationRedisSerializer.deserialize(serializeValue);
    }

    /**
     * 根据key删除缓存
     * @param key
     * @return
     */
    @Override
    public Object removeObject(Object key) {
        //使用工厂创建redis链接对象
        RedisConnection connection = jedisConnectionFactory.getConnection();
        //序列化key和value
        //1,实例化序列化和反序列对象
        JdkSerializationRedisSerializer  jdkSerializationRedisSerializer =new JdkSerializationRedisSerializer();
        //2,序列化K
        byte[] serializeKey = jdkSerializationRedisSerializer.serialize(key);
        //直接删除,但是不好,可能会影响redis效率
        //return connection.del(serializeKey);
        //设置立马过期,并不是真正的删除,redis底层会调用过期key的删除策略  批量删除,提高redis效率
        return connection.expire(serializeKey,0);
    }

    /**
     * 清空所有缓存
     */
    @Override
    public void clear() {
        //使用工厂创建redis链接对象
        RedisConnection connection = jedisConnectionFactory.getConnection();
        //清空当前库
        connection.flushDb();
        //清空所有库  使用主从或者哨兵,有16库时使用
        connection.flushAll();
    }

    /**
     * 获取缓存的数量
     * @return
     */
    @Override
    public int getSize() {
        //使用工厂创建redis链接对象
        RedisConnection connection = jedisConnectionFactory.getConnection();
        //获取当前库的key的数量
        Long aLong = connection.dbSize();
        //转换并返回
        return Integer.valueOf(aLong.toString());
    }

    /**
     * 对缓存的读写策略
     * @return
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }
}

缓存理论

https://mybatis.p2hp.com/sqlmap-xml.html#cache
Cache配置及第三方接口的讲解

映射语句文件中的所有 select 语句的结果将会被缓存。
映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
缓存不会定时进行刷新(也就是说,没有刷新间隔)。
缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

配置spring整合redis

package com.aaa.sbm.config;

import com.aaa.sbm.property.RedisProperty;
import com.aaa.sbm.util.MyCustomCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.Resource;

/**
 * @FileName: SpringRedisConfig
 * @Description: spring整合redis的配置
 * @Author: zhz
 * @CreateTime: 2024/12/5 9:44
 * @Version: 1.0.0
 */
@Configuration //相当于spring-redis-config.xml  <beans>
public class SpringRedisConfig {

    //常量  硬编码   魔法值
   // private final  static  String  CLUSTER_NODE_STR = "192.168.170.21:8001,192.168.170.21:8002,192.168.170.22:8003,192.168.170.22:8004,192.168.170.23:8005,192.168.170.23:8006";
   // private  final  static  Boolean TEST_ON_BORROW=false;

    @Resource
    private RedisProperty redisProperty;
    /**
     * 实例化jedisConnectionFactory
     * @return
     */
    @Bean  //<bean id='jedisConnectionFactory' class=org.springframework.data.redis.connection.jedis.JedisConnectionFactory>
    public JedisConnectionFactory jedisConnectionFactory(){
        //实例化  RedisClusterConfiguration clusterConfig, JedisPoolConfig poolConfig
        JedisConnectionFactory jedisConnectionFactory =new JedisConnectionFactory(clusterConfig(),poolConfig());
        return  jedisConnectionFactory;
    }

    /**
     * 把当前类配置好的jedisConnectionFactory对象注入到MyCustomCache中使用
     */
    @Bean
    public void setJCF(){
        MyCustomCache.setJedisConnectionFactory(jedisConnectionFactory());
    }

    /**
     * 实例化 redis的集群配置
     * @return
     */
    @Bean
    public RedisClusterConfiguration clusterConfig(){
        //实例化
        RedisClusterConfiguration redisClusterConfiguration  =new RedisClusterConfiguration();
        //"192.168.170.21:8001,192.168.170.21:8002,192.168.170.22:8003,192.168.170.22:8004,192.168.170.23:8005,192.168.170.23:8006";
        //hostAndPortArray=["192.168.170.21:8001","192.168.170.21:8002"...]
        String[] hostAndPortArray = redisProperty.getNodes().split(",");
        //循环
        for (String hostAndPort : hostAndPortArray) {
            //hostAndPort 第1次192.168.170.21:8001
            //hostAndPort 第1次192.168.170.21:8002
            //...
            String[] hostPort = hostAndPort.split(":");
            //实例化redis节点对象
            RedisNode node = new RedisNode(hostPort[0],Integer.valueOf(hostPort[1]));
            //添加集群节点
            redisClusterConfiguration.addClusterNode(node);
        }

        return redisClusterConfiguration;
    }

    /**
     * 实例化 redis的连接池配置
     * @return
     */
    @Bean
    public JedisPoolConfig poolConfig(){
        //实例化
        JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();
        //魔法值
        //连接池设置
         //使用连接时是否检查
        jedisPoolConfig.setTestOnBorrow(redisProperty.getTestOnBorrow());
        //归还链接时是否要检查
        jedisPoolConfig.setTestOnReturn(redisProperty.getTestOnReturn());
        //设置最大连接数
        jedisPoolConfig.setMaxTotal(redisProperty.getMaxTotal());
        //设置最大空闲时长
        jedisPoolConfig.setMaxIdle(redisProperty.getMaxIdle());
        //设置最大等待时长
        jedisPoolConfig.setMaxWaitMillis(redisProperty.getMaxWaitMillis());
        //....
        return  jedisPoolConfig;
    }

}

Mapper配置缓存

 <!--二级缓存   缓存到第三方redis内存-->
    <cache  type="com.aaa.sbm.util.MyCustomCache"></cache>

优化(防止硬编码和魔法值)
配置redis集群和连接池配置都是硬编码,不方便修改,连接池配置还有魔法值,在java代码规范中都是不允许。。。
配置

#配置rabbitmq
#rabbitmq.host=
#rabbitmq.port=

#配置druid
#druid.url=
#druid.username=


# redis连接池配置
#spirngboot+mybatis连接redis cluster配置
#最大能够保持空闲状态的链接数
redis.maxIdle=2000
#最大连接数
redis.maxTotal=20000
#最大的等待时长 毫秒
redis.maxWaitMillis=20000
#当调用borrow Object方法时,是否进行有效性检查
redis.testOnBorrow=false
redis.testOnReturn=false
#集群节点配置
redis.nodes=192.168.170.21:8001,192.168.170.21:8002,192.168.170.22:8003,192.168.170.22:8004,192.168.170.23:8005,192.168.170.23:8006
#企业中配置会更多   更深入的了解 配置,优化企业中实战使用

编写类

package com.aaa.sbm.property;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * @FileName: RedisProperity
 * @Description:
 * @Author: zhz
 * @CreateTime: 2024/12/5 11:04
 * @Version: 1.0.0
 */
@Component
@PropertySource("project.properties") //指定对应配置文件名称
@ConfigurationProperties(prefix = "redis")  //配置前缀为redis的
@Data
public class RedisProperty {
    //最大能够保持空闲状态的链接数
    private int maxIdle;
    //最大连接数
    private int maxTotal;
    //最大的等待时长 毫秒
    private int maxWaitMillis;
    //当调用borrow Object方法时,是否进行有效性检查
    private Boolean testOnBorrow;
    private Boolean testOnReturn;

    //集群节点配置
    private String nodes;

}

标签:缓存,redis,192.168,connection,key,import
From: https://www.cnblogs.com/xiaomubupi/p/18639413

相关文章

  • redis-1
    nosqlcpu,内存和磁盘的关系nosql简介NoSQL(notonlysql),泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在处理web2.0网站,特别是超大规模(京东,淘宝,天猫.......)和高并发的SNS(社交平台)类型的web2.0纯动态网站已经显得力不从心(基于磁盘存储),出现了很多难以克服......
  • 2024-12-25《linux上安装redis报错》
     在linux上安装redis时,首先要安装c/c++编译器,然后安装redis,不然redis跑不了,安装时报错:cdsrc&&makeallmake[1]:Enteringdirectory'/opt/redis-7.0.0/src'CCMakefile.depCCserver.oInfileincludedfromserver.c:30:server.h:57:10:fatalerror:systemd......
  • 腾讯音乐:说说Redis脑裂问题?
    Redis脑裂问题是指,在Redis哨兵模式或集群模式中,由于网络原因,导致主节点(Master)与哨兵(Sentinel)和从节点(Slave)的通讯中断,此时哨兵就会误以为主节点已宕机,就会在从节点中选举出一个新的主节点,此时Redis的集群中就出现了两个主节点的问题,就是Redis脑裂问题。脑裂问题影响......
  • linux中,redis哨兵和数据持久化存储
    redis哨兵:"主从同步增强架构","读写分离","高可用" 1.概念 是Redis主从同步的增强架构,可以实现Redis主从同步的读写分离和高可用 2.特性: 1、可以承接客户端连接,但不存储数据 2、实现Redis主从复制组的监控 3、实现Redis主从的读写分离 4、Redis主从复制组的故......
  • Redis-十大数据类型
    Reids数据类型指的是value的类型,key都是字符串redis-server:启动redis服务redis-cli:进入redis交互式终端常用的key的操作redis的命令和参数不区分大小写,key和value区分1、查看当前库所有的keykeys*2、判断某个key是否存在existskey3、查看key是什么类型......
  • Redis可视化工具推荐:Another Redis Desktop Manager使用教程与下载
    Redis是一种高性能的Key-Value数据库,被广泛应用于缓存、消息队列等场景。尽管Redis的命令行工具功能强大,但对于许多开发者而言,使用一款可视化工具可以大大提高操作效率和用户体验。今天为大家推荐一款功能强大的Redis可视化工具——AnotherRedisDesktopManager,并提供资源......
  • redis缓存穿透和 缓存雪崩
    在使用Redis作为缓存系统时,缓存穿透(CachePenetration)和缓存雪崩(CacheAvalanche)是两种常见的问题。它们会影响缓存系统的性能和稳定性。以下是这两种问题的详细解释及其解决方法。缓存穿透(CachePenetration)缓存穿透是指查询一个在缓存和数据库中都不存在的数据,导致请求直接......
  • 【Redis Zset】Redis Zset多字段排序方案设计
    背景最近拿到多个排行榜相关的需求,按财富值,魅力值等单个或多个字段进行排序默认取前N条数据,考虑使用Redis进行排行榜实现,数据结构使用zset,本文对财富值和魅力值二个或多个字段排序的思路进行说明; 需求背景排行榜,按财富值和魅力值进行倒序排序,优先财富值排序,财富值相同则取魅......
  • 日志文件爆满_开发脚本每小时自动检测日志大小_定期清理日志_生产环境redis宕机_无法
     今天日志数据占用磁盘爆满,正常运行的系统发生,redis无法写入的报错,导致共用的redis服务器,瘫痪了,很多系统都进不去了. 最后查了一下才知道,是因为磁盘上一个日志文件170多GB了,都是日志.看看怎么处理:首先编写一个脚本,用来循环检测,每一个小时检测文件大小,如果超过......
  • Redis篇--应用篇1--会话存储(session共享)
    1、概述实现Session共享是构建分布式Web应用时的一个重要需求,尤其是在水平扩展和高可用性要求较高的场景下。在分布式服务或集群服务中往往会出现这样一个问题:用户登录A服务后可以正常访问A服务中的接口。但是我们知道,分布式服务通常都是有多个微服务一起构建形成的。如果......