使用redis和spring集成实际中遇到的有关问题
使用redis和spring集成实际中遇到的问题
最近使用redis遇到一些问题,记录一下。
格式就不排了,有时间再弄吧。
一、版本信息
spring 4.2.5
mysql 5.1.18
mybatis 3.2.8
mybatis-spring 1.2.4
jedis 2.8.0
spring-data 1.7.1
... ...
二、jedis和spring集成
1. 配置数据源
2.配置Template
注:在spring事务中不执行Lua脚本可使用enableTransactionSupport,否则报java.lang.unsupportedclassversion
三、与springCache集成
四、关于取值异常问题
redis-cli取到序列化后的值【1】
stringRedisSerializer:
"\xac\xed\x00\x05t\x00\x011"
jdkRedisSerializer:
"\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x01"
总结:各个RedisSerializer序列化的值存入redis后,取值时,是不能切换取值的。因为序列化方式不同。
最近使用redis遇到一些问题,记录一下。
格式就不排了,有时间再弄吧。
一、版本信息
spring 4.2.5
mysql 5.1.18
mybatis 3.2.8
mybatis-spring 1.2.4
jedis 2.8.0
spring-data 1.7.1
... ...
二、jedis和spring集成
1. 配置数据源
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${redis.maxTotal}" /> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="minIdle" value="${redis.minIdle}" /> <property name="maxWaitMillis" value="${redis.maxWaitMillis}" /> <!--对拿到的connection进行validateObject校验 --> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> <!--在进行returnObject对返回的connection进行validateObject校验 --> <property name="testOnReturn" value="${redis.testOnReturn}" /> <!--定时对线程池中空闲的链接进行validateObject校验 --> <property name="testWhileIdle" value="${redis.testWhileIdle}" /> </bean> <bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}"/> <property name="port" value="${redis.port}"/> <property name="password" value="${redis.password}" /> <property name="timeout" value="${redis.timeout}" /> <property name="database" value="${redis.default.database}" /> <property name="poolConfig" ref="jedisPoolConfig"/> </bean> <bean id="redis4CacheConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}"/> <property name="port" value="${redis.port}"/> <property name="password" value="${redis.password}" /> <property name="timeout" value="${redis.timeout}" /> <property name="database" value="${redis.cache.database}" /> <property name="poolConfig" ref="jedisPoolConfig"/> </bean>
2.配置Template
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" /> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redisConnectionFactory" /> <property name="keySerializer" ref="stringRedisSerializer" /> <property name="hashKeySerializer" ref="stringRedisSerializer" /> <!-- 默认即为 jdkRedisSerializer --> <!-- <property name="valueSerializer" ref="jdkRedisSerializer" /> <property name="hashValueSerializer" ref="jdkRedisSerializer" /> --> <!-- <property name="enableTransactionSupport" value="true" /> --> </bean>
注:在spring事务中不执行Lua脚本可使用enableTransactionSupport,否则报java.lang.unsupportedclassversion
三、与springCache集成
<bean id="redis4CacheTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redis4CacheConnectionFactory" /> <property name="keySerializer" ref="stringRedisSerializer" /> </bean> <!-- 开启缓存注解 --> <cache:annotation-driven/> <!-- declare Redis Cache Manager --> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redis4CacheTemplate" /> <!-- 是否事务提交,如果事务回滚,缓存也回滚,默认false --> <property name="transactionAware" value="true" /> <!-- 默认有效期1d 3600*24 --> <property name="defaultExpiration" value="86400" /> </bean>
public abstract class BaseCache { public String generateKey(String... args) { return RedisUtil.generateKey(args); } @CacheEvict(allEntries = true) public abstract void clearCaches(Class<?> clazz); } @Component(ActivityCache.SERVICE_NAME) @CacheConfig(cacheNames = {ActivityCache.SERVICE_NAME}) public class ActivityCache extends BaseCache { /** * SERVICE_NAME:服务名 */ public static final String SERVICE_NAME = "activityCache"; @Autowired private ActivityDao activityDao; @Cacheable(key="#root.target.generateKey(#root.targetClass.getSimpleName(), #activityCode)", unless="#result == null") public Activity getActivityInfo(String activityCode){ Activity activity = null; try { } catch (Exception e) { log.error(e.getMessage(),e); } return activity; } @CachePut(key="#root.target.generateKey(#root.targetClass.getSimpleName(), #activity.activityCode)", unless="#result == null") public Activity saveOrUpdateActivityInfo(Activity activity) @CachePut(key="#root.target.generateKey(#root.targetClass.getSimpleName(), #activityCode)", unless="#result == null") public int delActivity(String activityCode) @CacheEvict(allEntries = true) public void clearCaches(Class<?> clazz) }
四、关于取值异常问题
Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:spring/spring.xml" // , // "classpath:spring/spring-mvc.xml", // "file:src/main/java/com/sinowel/eacpc/**/mapping/*.xml" }) public class TestBase { @Before public void setUp() throws Exception { } }
public class TestLua2 extends TestBase { private final Logger logger = LoggerFactory.getLogger(TestLua2.class); @Resource(name = RedisService.SERVICE_NAME) private RedisService redisService; // redis @Resource(name = "redisTemplate") private RedisTemplate<String, Object> redisTemplate; // redis @Test public void testInject() throws Exception { // 在服务器redis-cli连接预存入Hash key=tt1 field=t1,t2的数值 String redisKey = "tt1"; List<String> fieldList = Arrays.asList(new String[] {"t1", "t2"}); List<Long> list = redisService.getMultiHash(redisKey, fieldList, null); System.out.println(list.get(0).longValue()); // 存入时使用stringRedisSerializer,取值时使用jdkRedisSerializer。xml RedisTemplate时配置 // 异常,先存,再次取,配置文件切换配置 String redisKey = "tt2"; List<String> fieldList = Arrays.asList(new String[] {"t1", "t2"}); redisService.setHash(redisKey, "t1", "1"); redisService.setHash(redisKey, "t2", "2"); BoundHashOperations<String, String, Long> bhOps = redisTemplate .boundHashOps(redisKey); List<Long> list = bhOps.multiGet(fieldList); System.out.println(list.get(0)); // keySerializer 和 hashKeySerializer 设置 stringRedisSerializer // valueSerializer 和 hashValueSerializer 设置成默认 jdkRedisSerializer // 则可以取得指定值,否则都使用stringRedisSerializer,取到的值一定是String类型 String redisKey = "tt3"; List<String> fieldList = Arrays.asList(new String[] {"t1", "t2"}); BoundHashOperations<String, String, Long> bhOps = redisTemplate .boundHashOps(redisKey); bhOps.put("t1", 1L); bhOps.put("t2", 2L); List<Long> list = bhOps.multiGet(fieldList); System.out.println(list.get(0)); } }
redis-cli取到序列化后的值【1】
stringRedisSerializer:
"\xac\xed\x00\x05t\x00\x011"
jdkRedisSerializer:
"\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x01"
总结:各个RedisSerializer序列化的值存入redis后,取值时,是不能切换取值的。因为序列化方式不同。