一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數據庫技術|

服務器之家 - 數據庫 - Redis - Redis主從實現讀寫分離

Redis主從實現讀寫分離

2019-10-31 16:27KeySilenceM Redis

這篇文章主要為大家詳細介紹了Redis主從實現讀寫分離的相關資料 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下

前言

大家在工作中可能會遇到這樣的需求,即Redis讀寫分離,目的是為了壓力分散化。下面我將為大家介紹借助AWS的ELB實現讀寫分離,以寫主讀從為例。

實現

引用庫文件

?
1
2
3
4
5
6
<!-- redis客戶端 -->
<dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
 <version>2.6.2</version>
</dependency>

方式一,借助切面

JedisPoolSelector

此類的目的是為讀和寫分別配置不同的注解,用來區分是主還是從。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.silence.spring.redis.readwriteseparation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * Created by keysilence on 16/10/26.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JedisPoolSelector {
 
  String value();
 
}

JedisPoolAspect

此類的目的是針對主和從的注解,進行動態鏈接池調配,即主的使用主鏈接池,從的使用從連接池。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.silence.spring.redis.readwriteseparation;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import redis.clients.jedis.JedisPool;
 
import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Date;
 
/**
 * Created by keysilence on 16/10/26.
 */
@Aspect
public class JedisPoolAspect implements ApplicationContextAware {
 
  private ApplicationContext ctx;
 
  @PostConstruct
  public void init() {
    System.out.println("jedis pool aspectj started @" + new Date());
  }
 
  @Pointcut("execution(* com.silence.spring.redis.readwriteseparation.util.*.*(..))")
  private void allMethod() {
 
  }
 
  @Before("allMethod()")
  public void before(JoinPoint point)
  {
    Object target = point.getTarget();
    String method = point.getSignature().getName();
 
    Class classz = target.getClass();
 
    Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
        .getMethod().getParameterTypes();
    try {
      Method m = classz.getMethod(method, parameterTypes);
      if (m != null && m.isAnnotationPresent(JedisPoolSelector.class)) {
        JedisPoolSelector data = m
            .getAnnotation(JedisPoolSelector.class);
        JedisPool jedisPool = (JedisPool) ctx.getBean(data.value());
        DynamicJedisPoolHolder.putJedisPool(jedisPool);
      }
 
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
 
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.ctx = applicationContext;
  }
 
}

DynamicJedisPoolHolder

此類目的是存儲當前使用的JedisPool,即上面類賦值后的結果保存。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.silence.spring.redis.readwriteseparation;
 
import redis.clients.jedis.JedisPool;
 
/**
 * Created by keysilence on 16/10/26.
 */
public class DynamicJedisPoolHolder {
 
  public static final ThreadLocal<JedisPool> holder = new ThreadLocal<JedisPool>();
 
  public static void putJedisPool(JedisPool jedisPool) {
    holder.set(jedisPool);
  }
 
  public static JedisPool getJedisPool() {
    return holder.get();
  }
 
}

RedisUtils

此類目的是對Redis具體的調用,里面包含使用主還是從的方式調用。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.silence.spring.redis.readwriteseparation.util;
 
import com.silence.spring.redis.readwriteseparation.DynamicJedisPoolHolder;
import com.silence.spring.redis.readwriteseparation.JedisPoolSelector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * Created by keysilence on 16/10/26.
 */
public class RedisUtils {
  private static Logger logger = LoggerFactory.getLogger(RedisUtils.class);
 
  @JedisPoolSelector("master")
  public String setString(final String key, final String value) {
 
    String ret = DynamicJedisPoolHolder.getJedisPool().getResource().set(key, value);
    System.out.println("key:" + key + ",value:" + value + ",ret:" + ret);
 
    return ret;
  }
 
  @JedisPoolSelector("slave")
  public String get(final String key) {
 
    String ret = DynamicJedisPoolHolder.getJedisPool().getResource().get(key);
    System.out.println("key:" + key + ",ret:" + ret);
 
    return ret;
  }
 
}

spring-datasource.xml

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?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"
    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">
 
  <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 池中最大鏈接數 -->
    <property name="maxTotal" value="100"/>
    <!-- 池中最大空閑鏈接數 -->
    <property name="maxIdle" value="50"/>
    <!-- 池中最小空閑鏈接數 -->
    <property name="minIdle" value="20"/>
    <!-- 當池中鏈接耗盡,調用者最大阻塞時間,超出此時間將跑出異常。(單位:毫秒;默認為-1,表示永不超時) -->
    <property name="maxWaitMillis" value="1000"/>
    <!-- 參考:http://biasedbit.com/redis-jedispool-configuration/ -->
    <!-- 調用者獲取鏈接時,是否檢測當前鏈接有效性。無效則從鏈接池中移除,并嘗試繼續獲取。(默認為false) -->
    <property name="testOnBorrow" value="true" />
    <!-- 向鏈接池中歸還鏈接時,是否檢測鏈接有效性。(默認為false) -->
    <property name="testOnReturn" value="true" />
    <!-- 調用者獲取鏈接時,是否檢測空閑超時。如果超時,則會被移除(默認為false) -->
    <property name="testWhileIdle" value="true" />
    <!-- 空閑鏈接檢測線程一次運行檢測多少條鏈接 -->
    <property name="numTestsPerEvictionRun" value="10" />
    <!-- 空閑鏈接檢測線程檢測周期。如果為負值,表示不運行檢測線程。(單位:毫秒,默認為-1) -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
    <!-- 鏈接獲取方式。隊列:false;棧:true -->
    <!--<property name="lifo" value="false" />-->
  </bean>
 
  <bean id="master" class="redis.clients.jedis.JedisPool">
    <constructor-arg index="0" ref="poolConfig"/>
    <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/>
    <constructor-arg index="2" value="6379" type="int"/>
  </bean>
 
  <bean id="slave" class="redis.clients.jedis.JedisPool">
    <constructor-arg index="0" ref="poolConfig"/>
    <!-- 此處Host配置成ELB地址 -->
    <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/>
    <constructor-arg index="2" value="6380" type="int"/>
  </bean>
 
  <bean id="redisUtils" class="com.silence.spring.redis.readwriteseparation.util.RedisUtils">
  </bean>
 
  <bean id="jedisPoolAspect" class="com.silence.spring.redis.readwriteseparation.JedisPoolAspect" />
 
  <aop:aspectj-autoproxy proxy-target-class="true"/>
 
</beans>

Test

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.silence.spring.redis.readwriteseparation;
 
import com.silence.spring.redis.readwriteseparation.util.RedisUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * Created by keysilence on 16/10/26.
 */
public class Test {
 
  public static void main(String[] args) {
 
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-datasource.xml");
 
    System.out.println(ctx);
 
    RedisUtils redisUtils = (RedisUtils) ctx.getBean("redisUtils");
    redisUtils.setString("aaa", "111");
 
    System.out.println(redisUtils.get("aaa"));
  }
 
}

方式二,依賴注入

與方式一類似,但是需要寫死具體使用主的池還是從的池,思路如下:
放棄注解的方式,直接將主和從的兩個鏈接池注入到具體實現類中。

RedisUtils

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.silence.spring.redis.readwriteseparation.util;
 
import com.silence.spring.redis.readwriteseparation.DynamicJedisPoolHolder;
import com.silence.spring.redis.readwriteseparation.JedisPoolSelector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.JedisPool;
 
/**
 * Created by keysilence on 16/10/26.
 */
public class RedisUtils {
  private static Logger logger = LoggerFactory.getLogger(RedisUtils.class);
 
  private JedisPool masterJedisPool;
 
  private JedisPool slaveJedisPool;
 
  public void setMasterJedisPool(JedisPool masterJedisPool) {
    this.masterJedisPool = masterJedisPool;
  }
 
  public void setSlaveJedisPool(JedisPool slaveJedisPool) {
    this.slaveJedisPool = slaveJedisPool;
  }
 
  public String setString(final String key, final String value) {
 
    String ret = masterJedisPool.getResource().set(key, value);
    System.out.println("key:" + key + ",value:" + value + ",ret:" + ret);
 
    return ret;
  }
 
  public String get(final String key) {
 
    String ret = slaveJedisPool.getResource().get(key);
    System.out.println("key:" + key + ",ret:" + ret);
 
    return ret;
  }
 
}

spring-datasource.xml

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?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"
    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">
 
  <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 池中最大鏈接數 -->
    <property name="maxTotal" value="100"/>
    <!-- 池中最大空閑鏈接數 -->
    <property name="maxIdle" value="50"/>
    <!-- 池中最小空閑鏈接數 -->
    <property name="minIdle" value="20"/>
    <!-- 當池中鏈接耗盡,調用者最大阻塞時間,超出此時間將跑出異常。(單位:毫秒;默認為-1,表示永不超時) -->
    <property name="maxWaitMillis" value="1000"/>
    <!-- 參考:http://biasedbit.com/redis-jedispool-configuration/ -->
    <!-- 調用者獲取鏈接時,是否檢測當前鏈接有效性。無效則從鏈接池中移除,并嘗試繼續獲取。(默認為false) -->
    <property name="testOnBorrow" value="true" />
    <!-- 向鏈接池中歸還鏈接時,是否檢測鏈接有效性。(默認為false) -->
    <property name="testOnReturn" value="true" />
    <!-- 調用者獲取鏈接時,是否檢測空閑超時。如果超時,則會被移除(默認為false) -->
    <property name="testWhileIdle" value="true" />
    <!-- 空閑鏈接檢測線程一次運行檢測多少條鏈接 -->
    <property name="numTestsPerEvictionRun" value="10" />
    <!-- 空閑鏈接檢測線程檢測周期。如果為負值,表示不運行檢測線程。(單位:毫秒,默認為-1) -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
    <!-- 鏈接獲取方式。隊列:false;棧:true -->
    <!--<property name="lifo" value="false" />-->
  </bean>
 
  <bean id="masterJedisPool" class="redis.clients.jedis.JedisPool">
    <constructor-arg index="0" ref="poolConfig"/>
    <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/>
    <constructor-arg index="2" value="6379" type="int"/>
  </bean>
 
  <bean id="slaveJedisPool" class="redis.clients.jedis.JedisPool">
    <constructor-arg index="0" ref="poolConfig"/>
    <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/>
    <constructor-arg index="2" value="6380" type="int"/>
  </bean>
 
  <bean id="redisUtils" class="com.silence.spring.redis.readwriteseparation.util.RedisUtils">
    <property name="masterJedisPool" ref="masterJedisPool"/>
    <property name="slaveJedisPool" ref="slaveJedisPool"/>
  </bean>
 
</beans>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
  • RedisRedis如何實現數據庫讀寫分離詳解

    Redis如何實現數據庫讀寫分離詳解

    Redis的主從架構,能幫助我們實現讀多,寫少的情況,下面這篇文章主要給大家介紹了關于Redis如何實現數據庫讀寫分離的相關資料,文中通過示例代碼介紹...

    羅兵漂流記6092019-11-11
  • Redisredis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友...

    xiaojin21cen10152021-07-27
  • Redisredis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    這篇文章主要給大家介紹了關于redis中如何使用lua腳本讓你的靈活性提高5個逼格的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具...

    一線碼農5812019-11-18
  • Redisredis實現排行榜功能

    redis實現排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用來實現排行榜功能,本文就來簡單的介紹一下如何使用,具有一定的參考價值,感興趣的小伙伴們...

    乘月歸5022021-08-05
  • Redis詳解Redis復制原理

    詳解Redis復制原理

    與大多數db一樣,Redis也提供了復制機制,以滿足故障恢復和負載均衡等需求。復制也是Redis高可用的基礎,哨兵和集群都是建立在復制基礎上實現高可用的...

    李留廣10222021-08-09
  • RedisRedis全量復制與部分復制示例詳解

    Redis全量復制與部分復制示例詳解

    這篇文章主要給大家介紹了關于Redis全量復制與部分復制的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Redis爬蟲具有一定的參考學習...

    豆子先生5052019-11-27
  • RedisRedis的配置、啟動、操作和關閉方法

    Redis的配置、啟動、操作和關閉方法

    今天小編就為大家分享一篇Redis的配置、啟動、操作和關閉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    大道化簡5312019-11-14
  • RedisRedis 事務知識點相關總結

    Redis 事務知識點相關總結

    這篇文章主要介紹了Redis 事務相關總結,幫助大家更好的理解和學習使用Redis,感興趣的朋友可以了解下...

    AsiaYe8232021-07-28
主站蜘蛛池模板: 久久亚洲伊人 | youjizzxxx在线观看 | 日本高清视频在线观看 | 国产成人yy精品1024在线 | 国模李丽莎大尺度啪啪 | 2019国内精品久久久久久 | 人与禽交3d动漫羞羞动漫 | 99热这里只有精品一区二区三区 | 国产成人福利免费观看 | 538亚洲欧美国产日韩在线精品 | 男人的j放进女人的p全黄 | 不卡一区二区三区卡 | 四虎影院精品在线观看 | 国产情侣偷国语对白 | 久久青青草原精品国产软件 | 成人天堂入口网站 | 国产拍拍视频一二三四区 | 国产自产在线 | 欧美成人tv | 国产精品女主播大秀在线 | 高清视频在线播放 | 四虎影视在线看免费 720p | 国产精品露脸国语对白河北 | 男人的天堂在线观看视频不卡 | 久久免费观看视频 | 精品女同一区二区三区免费站 | 2022国产麻豆剧传媒剧情 | 互换身体全集免费观看 | 久久偷拍人 | 欧美午夜网站 | 麻豆在线观看 | 91精品国产91热久久久久福利 | 国产精品全国探花在线观看 | 污小说h| 国产婷婷成人久久av免费高清 | 动漫美女隐私尿口图片 | 青青青国产精品国产精品久久久久 | 美日韩一区二区三区 | 天天快乐高清在线观看 | 国产精品每日在线观看男人的天堂 | 538亚洲欧美国产日韩在线精品 |