Problemas y soluciones encontrados por Spring usando redis

Uno, archivo de configuración

<!-- 加载Properties文件 -->
  <bean id="configurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
      <list>
        <value>classpath*:config.properties</value>
      </list>
    </property>
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
  </bean>

  <!-- 配置JedisPoolConfig实例 -->
  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!--最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制-->
    <property name="maxIdle" value="300" />
    <!--连接池的最大数据库连接数。设为0表示无限制-->
    <property name="maxTotal" value="600" />
    <!--最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制-->
    <property name="maxWaitMillis" value="1000" />
    <!--在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的-->
    <property name="testOnBorrow" value="true" />
    <!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3-->
    <property name="numTestsPerEvictionRun" value="3"/>
    <!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟)-->
    <property name="minEvictableIdleTimeMillis" value="300000"/>
    <!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1-->
    <property name="timeBetweenEvictionRunsMillis" value="60000"/>
    <!--在空闲时检查有效性, 默认false -->
    <property name="testWhileIdle" value="true" />
  </bean>

  <!-- 配置JedisConnectionFactory,类似于数据库的连接池 -->
  <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="${redis.host}"></property>
    <property name="port" value="${redis.port}"></property>
    <property name="password" value="${redis.password}"></property>
    <property name="database" value="${redis.dbIndex}"></property>
    <property name="poolConfig" ref="jedisPoolConfig"></property>
    <property name="timeout" value="100000"></property>
  </bean>

  <!-- 配置RedisTemplate -->
  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory"></property>
    <!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!! -->
    <property name="keySerializer" >
      <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    </property>
    <property name="valueSerializer" >
      <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />
    </property>
    <property name="hashKeySerializer">
      <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    </property>
    <property name="hashValueSerializer">
      <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
    </property>
    <!--开启事务 -->
    <property name="enableTransactionSupport" value="true"></property>
  </bean>

Nota: Puede ver que en mi configuración de redis, la serialización StringRedisSerializer se usa para la clave hash y la serialización GenericJackson2JsonRedisSerializer se usa para el valor.

Segundo, pozo uno

// 源代码
HashOperations ho = redisTemplate.opsForHash();
Boolean flag = ho.hasKey(“key”, "key1");
if (flag) {
  // 处理逻辑
}

El código anterior, cuando el valor en redis no existe, según la documentación oficial, debe devolver falso. Pero cuando lo uso, el método hasKey a veces devuelve nulo y, a veces, falso, lo que resulta en una excepción de puntero nulo. Después de hacerlo durante mucho tiempo, no me di cuenta de por qué devolvía falso. Al final, no había forma de comprometerme (el dios puede responderme si lo sabe).

// 妥协后代码
HashOperations ho = redisTemplate.opsForHash();
Boolean flag = ho.hasKey(“key”, "key1");
if (flag != null && flag) {
  // 处理逻辑
}

Tres, pozo dos

// 将Map放到redis的hash中
  public void putRedisHash1(){
    HashOperations ho = redisTemplate.opsForHash();
    Map<String, Boolean> tempMap = new HashMap<String, Boolean>(3){
   
   {
      put("isRegistered",false);
      put("isWeChat",false);
      put("isAliPay",false);
    }};
    ho.put("key", "key1", tempMap);
  }

  // 将Map放到redis的hash中
  public void putRedisHash2(){
    HashOperations ho = redisTemplate.opsForHash();
    Map<String, Boolean> tempMap = new HashMap<String, Boolean>(3);
    tempMap.put("isRegistered",false);
    tempMap.put("isWeChat",false);
    tempMap.put("isAliPay",false);
    ho.put("key", "key1", tempMap);
  }

Las funciones de estos dos métodos son las mismas, pero el primer método consiste en poner el valor en él al mismo tiempo que se inicializa el mapa. El segundo método es poner el valor en él después de inicializar el mapa. El resultado de la ejecución es el mismo, pero en redis El formato de almacenamiento es completamente diferente. Dado que el valor de Hash se serializa usando GenericJackson2JsonRedisSerializer, lo almacenará para la conveniencia de la deserialización

El campo @class "", debido a la diferente sincronización de la inicialización del mapa, hace que el mismo contenido sea inconsistente en el contenido de @class en redis. Para facilitar el uso, se recomienda el segundo método, que consiste en poner el valor en después de inicializar el mapa.


Algunas preguntas de entrevistas de alta frecuencia recopiladas en el último 2020 (todas organizadas en documentos), hay muchos productos secos, incluidos mysql, netty, spring, thread, spring cloud, jvm, código fuente, algoritmo y otras explicaciones detalladas, así como planes de aprendizaje detallados, entrevistas Clasificación de preguntas, etc. Para aquellos que necesitan obtener estos contenidos, agregue Q como: 11604713672

Supongo que te gusta

Origin blog.csdn.net/weixin_51495453/article/details/113958814
Recomendado
Clasificación