在對(duì)Redis進(jìn)行性能優(yōu)化時(shí),一直想對(duì)Redis進(jìn)行讀寫分離。但由于項(xiàng)目底層采用spring-data-redis對(duì)redis進(jìn)行操作,參考spring官網(wǎng)卻發(fā)現(xiàn)spring-data-redis目前(1.7.0.RELEASE)及以前的版本并不支持讀寫分離。
一、源碼分析
spring-data-redis中關(guān)于JedisConnectionFactory的配置如下:
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"> <bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"> <bean class="org.springframework.data.redis.connection.RedisNode"> <property name="name" value="mymaster"/> <constructor-arg name="host" value="${redis.master.host}"></constructor-arg> <constructor-arg name="port" value="${redis.master.port}"></constructor-arg> </bean> </property> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel1.host}"></constructor-arg> <constructor-arg name="port" value="${redis.sentinel1.port}"></constructor-arg> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel2.host}"></constructor-arg> <constructor-arg name="port" value="${redis.sentinel2.port}"></constructor-arg> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel3.host}"></constructor-arg> <constructor-arg name="port" value="${redis.sentinel3.port}"></constructor-arg> </bean> </set> </property> </bean> <!-- 連接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${redis.pool.maxActive}" /> <property name="maxIdle" value="${redis.pool.maxIdle}" /> <!-- <property name="maxWait" value="${redis.pool.maxWait}" /> --> <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /> <property name="testOnReturn" value="${redis.pool.testOnReturn}" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="poolConfig" ref="jedisPoolConfig"></property> <constructor-arg ref="redisSentinelConfiguration"/> </bean> <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="jedisConnectionFactory"/></beans>
查看JedisConnectionFactory源碼發(fā)現(xiàn)pool是Pool<Jedis>,而不是Pool<ShardedJedis>。因此我猜目前spring data redis是做不了讀寫分離的,stringRedisTemplate讀寫操作都是在master上。
二、讀寫分離改造
參考sentinel的主備選舉機(jī)制對(duì)spring-data-redis的相關(guān)配置進(jìn)行如下改造:
讀寫分離原理如下所示:
(1)Spring配置
(2)TWJedisConnectionFactory
(3)TWReadOnlyJedisConnectionFactory
(4)TWRedisTemplate
(5)JedisReadOnlyPool
(6)JedisSentinelSlavesPool
(7)RedisCacheService
在具體使用緩存服務(wù)時(shí),在讀、寫緩存時(shí)分別加上其類型
聯(lián)系客服