Jedis怎样实现只写master,只读slave

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jedis怎样实现只写master,只读slave相关的知识,希望对你有一定的参考价值。

参考技术A 一、配置
仅需要在slave node上修改配置:
找到slaveof这行,参考下面的修改(填上master node的Ip和端口就完事了)
slaveof 10.6.144.155 7030
另外注意下 slave-read-only yes 这行,这表示slave只读不写,也是设置

二、验证
启动master/slave这二台机器上的redis,在master上加一个缓存项

然后在slave上取出该缓存项

取到了,说明master上的cache自动复制到slave节点了

三、redisson客户端使用
View Code
注:经实际测试,redisson客户端在set写操作时,连接的是master node,get读操作时连接的是slave,而且遇到操作失败,会同步阻塞后面的处理(一直等待,直到超时)
即:set操作时,至少要有一台可连接的master,get操作时,至少要有一台可连接的slave

四、Jedis客户端使用
View Code

后记:个人感觉master-slave模式作用有限,因为从二种client的测试结果看,在没有其它监控机制的前提下,无论是master或slave挂掉,都需要手动调整配置或修改代码,才能保证读/写继续正常工作,理想情况是master挂掉,最好slave中能自动(无需人工干预)选出一台充当master继续服务。redis 的cluster功能,目前尚处于beta阶段,估计不久的将来,等cluster功能正式发布后,可以通过custer功能搭建redis集群。

redis的sentinel主从切换(failover)与Jedis线程池自动重连

本文介绍如何通过sentinel监控redis主从集群,并通过jedis自动切换ip和端口。

1、配置redis主从实例

10.93.21.21:6379

10.93.21.21:6389

10.93.21.21:6399

主从同步关系

master:10.93.21.21:6379

slave:10.93.21.21:6389,10.93.21.21:6399

master配置如下:

# 实例ip和端口
bind 10.93.21.21
port 6379
# pid文件
pidfile redis_6379.pid
# 日志文件
logfile "/home/data_monitor/redis-3.2.9/log/6379.log"
# 持久化数据文件dir
dir /home/data_monitor/redis-3.2.9/data
# rdb 文件地址
dbfilename 6379.rdb
# aof 文件地址
appendfilename "6379.aof"

slave配置如下(以6389为例)

# 实例ip和端口
bind 10.93.21.21
port 6389
# master节点配置
slaveof 10.93.21.21 6379
# pid文件
pidfile redis_6389.pid
# 日志文件
logfile "/home/data_monitor/redis-3.2.9/log/6389.log"
# 持久化数据文件dir
dir /home/data_monitor/redis-3.2.9/data
# rdb 文件地址
dbfilename 6389.rdb
# aof 文件地址
appendfilename "6389.aof"

启动redis

bin/redis-server conf/6379.conf
bin/redis-server conf/6389.conf
bin/redis-server conf/6399.conf

 验证一下

master

$ bin/redis-cli -h 10.93.21.21 -p 6379
10.93.21.21:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.93.21.21,port=6389,state=online,offset=571888,lag=1
slave1:ip=10.93.21.21,port=6399,state=online,offset=571888,lag=1
master_repl_offset:571888
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:571887

slave

$ bin/redis-cli -h 10.93.21.21 -p 6389
10.93.21.21:6389> info replication
# Replication
role:slave
master_host:10.93.21.21
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:530211
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

 

2、配置sentinel集群

10.93.21.21:26379

10.93.21.21:26389

10.93.21.21:26399

启动所有的节点,只要监控同一个redis master,启动的话自动连接成集群

# sentinel注册的IP和端口
bind 10.93.21.21
port 26379
# working目录
dir /home/data_monitor/redis-3.2.9/sentinel
# sentinel监控哪个主节点
sentinel monitor mymaster 10.93.21.21 6379 1
# 主节点挂掉多长时间,判定为挂掉,开始failover
sentinel down-after-milliseconds mymaster 10000
# failover交由几个sentinel执行
sentinel parallel-syncs mymaster 1
# failover多长时间没完成,超时失败
sentinel failover-timeout mymaster 180000

启动sentinel集群

bin/redis-sentinel conf/s26379.conf
bin/redis-sentinel conf/s26389.conf
bin/redis-sentinel conf/s26399.conf

 

3、jedis自动切换ip和端口

先解决依赖:pom.xml

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.7.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>    

连接池代码

public class JedisPoolUtil {
     
    private static JedisSentinelPool pool = null;
 
    public static Properties getJedisProperties() {
 
        Properties config = new Properties();
        InputStream is = null;
        try {
            is = JedisPoolUtil.class.getClassLoader().getResourceAsStream("cacheConfig.properties");
            config.load(is);
        } catch (IOException e) {
            logger.error("", e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    logger.error("", e);
                }
            }
        }
        return config;
    }
 
    /**
     * 创建连接池
     *
     */
    private static void createJedisPool() {
        // 建立连接池配置参数
        JedisPoolConfig config = new JedisPoolConfig();
        Properties prop = getJedisProperties();
        // 设置最大连接数
        config.setMaxTotal(StringUtil.nullToInteger(prop.getProperty("MAX_ACTIVE")));
        // 设置最大阻塞时间,记住是毫秒数milliseconds
        config.setMaxWaitMillis(StringUtil.nullToInteger(prop.getProperty("MAX_WAIT")));
        // 设置空间连接
        config.setMaxIdle(StringUtil.nullToInteger(prop.getProperty("MAX_IDLE")));
        // jedis实例是否可用
        boolean borrow = prop.getProperty("TEST_ON_BORROW") == "false" ? false : true;
        config.setTestOnBorrow(borrow);
        // 创建连接池
//      pool = new JedisPool(config, prop.getProperty("ADDR"), StringUtil.nullToInteger(prop.getProperty("PORT")), StringUtil.nullToInteger(prop.getProperty("TIMEOUT")));// 线程数量限制,IP地址,端口,超时时间
        //获取redis密码
        String password = StringUtil.nullToString(prop.getProperty("PASSWORD"));
 
         String masterName = "mymaster";
        Set<String> sentinels = new HashSet<String>();
        sentinels.add("192.168.137.128:26379");
        sentinels.add("192.168.137.128:26380");
        sentinels.add("192.168.137.128:26381");
        pool = new JedisSentinelPool(masterName, sentinels, config);
    }
 
    /**
     * 在多线程环境同步初始化
     */
    private static synchronized void poolInit() {
        if (pool == null)
            createJedisPool();
    }
 
    /**
     * 获取一个jedis 对象
     *
     * @return
     */
    public static Jedis getJedis() {
        if (pool == null)
            poolInit();
        return pool.getResource();
    }
 
    /**
     * 释放一个连接
     *
     * @param jedis
     */
    public static void returnRes(Jedis jedis) {
        pool.returnResource(jedis);
    }
 
    /**
     * 销毁一个连接
     *
     * @param jedis
     */
    public static void returnBrokenRes(Jedis jedis) {
        pool.returnBrokenResource(jedis);
    }
     
     
    public static void main(String[] args){
        Jedis jedis=getJedis();
         
    }
 
}

 

以上是关于Jedis怎样实现只写master,只读slave的主要内容,如果未能解决你的问题,请参考以下文章

mysql一主多从怎样切

MongoDB

MongoDB副本集

redis的sentinel主从切换(failover)与Jedis线程池自动重连

redis集群

MySQL -MMM 学习整理