• redis客户端cluster集群模式整合


    一、pom文件引入redis依赖

    <!-- redis 版本 -->
    <redis.version>2.9.0</redis.version>
    <spring.redis.version>1.8.1.RELEASE</spring.redis.version>
    <!-- redis -->
    <dependency>
        <groupId>commons-pool</groupId>
        <artifactId>commons-pool</artifactId>
        <version>1.5.6</version>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>${redis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>${spring.redis.version}</version>
    </dependency>
    </dependencies>

    二、redis的可配置化参数

    redis.properties配置参数

    # JedisPoolConfig的参数
    # 最大连接数
    redis.pool.maxTotal=30
    # 最大空闲时间
    redis.pool.maxIdle=10
    # 每次最大连接数
    redis.pool.numTestsPerEvictionRun=1024
    # 释放扫描的扫描间隔
    redis.pool.timeBetweenEvictionRunsMillis=30000
    # 连接的最小空闲时间
    redis.pool.minEvictableIdleTimeMillis=1800000
    # 连接控歘按时间多久后释放,当空闲时间>该值且空闲连接>最大空闲连接数时直接释放
    redis.pool.softMinEvictableIdleTimeMillis=10000
    # 获得链接时的最大等待毫秒数,小于0:阻塞不确定时间,默认-1
    redis.pool.maxWaitMillis=1500
    # 在获得链接的时候检查有效性,默认false
    redis.pool.testOnBorrow=true
    # 在空闲时检查有效性,默认false
    redis.pool.testWhileIdle=true
    # 连接耗尽时是否阻塞,false报异常,true阻塞超时,默认true
    redis.pool.blockWhenExhausted=false
    
    # redis集群中的密码
    redis.password=han.sun
    
    # RedisClusterConfiguration配置
    redis.maxRedirects=6
    
    # 主机和端口号
    redis.host1=127.0.0.1
    redis.port1=7001
    redis.host2=127.0.0.1
    redis.port2=7002
    redis.host3=127.0.0.1
    redis.port3=7003
    redis.host4=127.0.0.1
    redis.port4=7004
    redis.host5=127.0.0.1
    redis.port5=7005
    redis.host6=127.0.0.1
    redis.port6=7006

    三、spring和redis整合

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.eastrobot.robotdev"/>
    
        <!-- 加载配置文件 -->
        <bean id="annotationPropertyConfigurerRedis"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="order" value="1"/>
            <property name="ignoreUnresolvablePlaceholders" value="true"/>
            <property name="locations">
                <list>
                    <value>classpath:redis.properties</value>
                </list>
            </property>
        </bean>
    
        <!--配置 jedis pool-->
        <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
            <!-- 最大连接数 -->
            <property name="maxTotal" value="${redis.pool.maxTotal}"/>
            <!-- 最大空闲时间 -->
            <property name="maxIdle" value="${redis.pool.maxIdle}"/>
            <!-- 每次最大连接数 -->
            <property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"/>
            <!-- 释放扫描的扫描间隔 -->
            <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"/>
            <!-- 连接的最小空闲时间 -->
            <property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"/>
            <!-- 连接空闲按时间多久后释放,当空闲时间大于该值且空闲连接>最大空闲连接数时直接释放 -->
            <property name="softMinEvictableIdleTimeMillis" value="${redis.pool.softMinEvictableIdleTimeMillis}"/>
            <!-- 获得连接时的最大等待毫秒数,小于0:阻塞不确定时间,默认-1 -->
            <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/>
            <!-- 在获得连接的时候检查有效性,默认false -->
            <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
            <!-- 在空闲时检查有效性,默认false -->
            <property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>
            <!-- 连接耗尽时是否阻塞,false报异常,true阻塞超时 默认:true-->
            <property name="blockWhenExhausted" value="${redis.pool.blockWhenExhausted}"/>
        </bean>
    
    
        <!--配置RedisClusterConfiguration-->
        <bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
            <property name="maxRedirects" value="${redis.maxRedirects}"/>
            <property name="clusterNodes">
                <set>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="${redis.host1}"/>
                        <constructor-arg name="port" value="${redis.port1}"/>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="${redis.host2}"/>
                        <constructor-arg name="port" value="${redis.port2}"/>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="${redis.host3}"/>
                        <constructor-arg name="port" value="${redis.port3}"/>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="${redis.host4}"/>
                        <constructor-arg name="port" value="${redis.port4}"/>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="${redis.host5}"/>
                        <constructor-arg name="port" value="${redis.port5}"/>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="${redis.host6}"/>
                        <constructor-arg name="port" value="${redis.port6}"/>
                    </bean>
                </set>
            </property>
        </bean>
    
        <!-- Spring-redis连接池管理工厂 -->
        <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
            <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
            <constructor-arg name="clusterConfig" ref="redisClusterConfiguration"/>
            <property name="password" value="${redis.password}"/>
        </bean>
    
        <!--redisTemplate-->
        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
            <property name="connectionFactory" ref="jedisConnectionFactory"/>
            <property name="keySerializer">
                <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
            </property>
            <!-- 如果想设置value为对象的话,这里不能配置成StringRedisSerializer -->
            <!-- 否则会报错  java.lang.ClassCastException: com.eastrobot.robotdev.entity.User cannot be cast to java.lang.String -->
            <!-- 而是要用JdkSerializationRedisSerializer,然后javabean实现Serializable接口 -->
            <property name="valueSerializer">
                <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
            </property>
            <property name="hashKeySerializer">
                <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
            </property>
            <property name="hashValueSerializer">
                <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
            </property>
    
            <!--开启事务  -->
            <property name="enableTransactionSupport" value="true"/>
        </bean>
    
    
    </beans>

    四、测试

    public class ServiceTest extends BaseTest {
    
        private static final Logger log = LogManager.getLogger(ServiceTest.class);
    
    
        @Autowired
        private RedisTemplate<String, String> redisTemplate;
    
    
        @Test
        public void test1() {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
    
            // 存入key-value
            operations.set("name2", "zhangsan123");
    
            // 根据key取出Value
            Object name = operations.get("name2");
            System.out.println("name2:" + name);
    
            // 追加
            operations.append("name2", "is man");
            name = operations.get("name2");
            System.out.println("name2:" + name);
    
            // 获得并修改
            operations.getAndSet("name2", "xiaoijiqiren");
            name = operations.get("name2");
            System.out.println("修改后:" + name);
        }
    
        @Test
        public void boundValueOperations() {
            String key = "name1";
            /*
             * 先获取redis对value的操作对象,需要先设定key
             */
            BoundValueOperations<String, String> stringTemplate = redisTemplate.boundValueOps(key);
    
            //赋值key
            stringTemplate.set("test123424");
            //获取value
            String value = stringTemplate.get();
            System.out.println(key + "的值为:" + value);
    
            //从value下标,第0位开始替换原有字符串
            stringTemplate.set("test1", 0);
            String value1 = stringTemplate.get();
            System.out.println(key + "的值为:" + value1);
    
            //从value下标,第1位开始替换原有字符
            stringTemplate.set("test2", 1);
            String value2 = stringTemplate.get();
            System.out.println(key + "的值为:" + value2);
    
            //从value下标第7位进行替换,如果超过原有字符串长度,差额中间补齐并且则将原有字符串跟新的进行拼接,
            stringTemplate.set("test3", 7);
            String value3 = stringTemplate.get();
            System.out.println(key + "的值为:" + value3);
    
            /*
             * 设置value缓存时间 V value, long timeout, TimeUnit unit
             *     三个字段分别对应 value,缓存时间,缓存单位,例如天,小时等,具体的,看TimeUnit源码
             */
            //设置超时时间为1天
            stringTemplate.set("testTimeout", 1, TimeUnit.DAYS);
            //获取缓存时间,单位 秒
            Long expire = stringTemplate.getExpire();
            System.out.println(key + "的缓存时间为:" + expire);
        }
    
    
        @Test
        public void testList() {
            ListOperations<String, String> ops = redisTemplate.opsForList();
            List<String> list = new ArrayList<>();
            list.add("sunhan");
            list.add("lisi");
            list.add("xiaoming");
    
            ops.leftPushAll("list1", list);
            ops.rightPushAll("list2", list);
    
            List list1 = ops.range("list1", 0, -1);
            for (Object o : list1) {
                log.info("1字段:{}", o);
            }
            List list2 = ops.range("list2", 0, -1);
            for (Object o : list2) {
                log.info("2字段:{}", o);
            }
        }
    
    
        @Test
        public void testListPop() {
            ListOperations<String, String> ops = redisTemplate.opsForList();
            // 获取到list的长度
            log.info("list1长度:{}", ops.size("list1"));
            log.info("list2长度:{}", ops.size("list2"));
            // 获取 列表下标的元素,如果下标越界获取的数据为null
            log.info(ops.index("list1", 1));
            // pop取栈头、栈尾
            log.info(ops.leftPop("list2"));
            log.info(ops.rightPop("list2"));
    
            //
            log.info(ops.remove("list2", 0, "sunhan"));
    
        }
    
    
    }

    五、发生的问题

    • 1、spring-data-redis代码进行存储, 客户端却取不到数据

      原因:如果key没做序列化存储,实际存进去的key前面会多几个字符,如果你用redis客户端查询你想要的key,
      最好在程序里对key进行序列化,这样最终的key值才是你想要的key,redisTemplate下面有这两个属性
      <property name="keySerializer"> 
      <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> 
      </property> 
      <property name="hashKeySerializer"> 
      <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> 
      </property> 
      springBoot做法:
      @Configuration
      public class RedisConfig {
      
          @Bean
          JedisConnectionFactory jedisConnectionFactory() {
              return new JedisConnectionFactory();
          }
      
          @Bean
          public <T> RedisTemplate<String, T> redisTemplate(RedisConnectionFactory factory) {
              RedisTemplate<String, T> template = new RedisTemplate<String, T>();
              template.setConnectionFactory(factory);
      //1.序列化key
              template.setKeySerializer(new StringRedisSerializer());//spring自带
      //2.序列划value
              template.setValueSerializer(new RedisObjectSerializer());//自定义
              return template;
          }
      
      }
  • 相关阅读:
    vscode使用SSH Targets连接远程系统进行开发
    python2.7版本安装pip
    ubuntu系统安装最新版本nodejs
    win7安装yarn后执行报错
    Object合并,并使用默认值处理
    解决JSON.stringify序列化循环依赖对象报错
    docker环境下安装maven私服和gitlab
    单例模式的无锁实现
    【Java学习笔记】Java的垃圾回收机制
    Ubuntu下源码安装Python
  • 原文地址:https://www.cnblogs.com/han-sun/p/12837767.html
Copyright © 2020-2023  润新知