Spring Boot JedisCluster

简述

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API

配置

1、添加Maven依赖 (或jar包)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、配置数据源相关信息

#redis cluster  
mc.cluster=192.168.10.20:6000,192.168.10.20:6001,192.168.10.20:6002,192.168.10.20:6003,192.168.10.20:6004,192.168.10.20:6005
mc.commandTimeout=5000

3、配置Redis

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Configuration
@ConditionalOnClass({JedisCluster.class})
public class JedisClusterConfig {
    @Value("#{'${mc.cluster}'.split(',')}")
    private List<String> clusterIpPortList;

    @Value("${mc.commandTimeout:5000}")
    private Integer commandTimeout;

    @Bean
    public JedisCluster getJedisCluster() {
        Set<HostAndPort> nodes = new HashSet<>();
        for (String ipPort : clusterIpPortList) {
            String[] ipPortPair = ipPort.split(":");
            nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
        }
        return new JedisCluster(nodes, commandTimeout);
    }
}

4、测试

Maven 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Junit

import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.cl.config.Application;

import redis.clients.jedis.JedisCluster;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class) // 指定spring-boot的启动类  
@WebAppConfiguration
public class TestJedis {

    private Logger logger = Logger.getLogger(getClass());

    @Autowired
    private JedisCluster jedisCluster;

    @Test
    public void testJedis() {
        jedisCluster.set("test_jedis_cluster", "38967");
        String string = jedisCluster.get("test_jedis_cluster");
        logger.info(string);
        jedisCluster.del("test_jedis_cluster");
    }
}

LUA

需要注意keys要在相同的Slot可考虑使用 hash tag 即在key中加入{相同标识}

JedisCluster.java

/**
 * 执行lua脚本
 * <p>
 * 需要注意keys要在相同的Slot
 * 可考虑使用 hash tag 即在key中加入{相同标识}
 * </p>
 */
@Override
public Object eval(final String script, final List<String> keys, final List<String> args) {
    return new JedisClusterCommand<Object>(connectionHandler, maxAttempts) {
        @Override
        public Object execute(Jedis connection) {
            return connection.eval(script, keys, args);
        }
    }.run(keys.size(), keys.toArray(new String[keys.size()]));
}

slot检测

public T run(int keyCount, String... keys) {
  if (keys == null || keys.length == 0) {
    throw new JedisClusterException("No way to dispatch this command to Redis Cluster.");
  }

  // For multiple keys, only execute if they all share the
  // same connection slot.
  if (keys.length > 1) {
    int slot = JedisClusterCRC16.getSlot(keys[0]);
    for (int i = 1; i < keyCount; i++) {
      int nextSlot = JedisClusterCRC16.getSlot(keys[i]);
      if (slot != nextSlot) {
        throw new JedisClusterException("No way to dispatch this command to Redis Cluster "
            + "because keys have different slots.");
      }
    }
  }

JedisClusterCRC16.getSlot(String key)

public static int getSlot(String key) {
  key = JedisClusterHashTagUtil.getHashTag(key);
  // optimization with modulo operator with power of 2
  // equivalent to getCRC16(key) % 16384
  return getCRC16(key) & (16384 - 1);
}

JedisClusterHashTagUtil.getHashTag(String key)

public final class JedisClusterHashTagUtil {

  private JedisClusterHashTagUtil() {
    throw new InstantiationError("Must not instantiate this class");
  }

  public static String getHashTag(String key) {
    return extractHashTag(key, true);
  }

  public static boolean isClusterCompliantMatchPattern(String matchPattern) {
    String tag = extractHashTag(matchPattern, false);
    return tag != null && !tag.isEmpty();
  }

  private static String extractHashTag(String key, boolean returnKeyOnAbsence) {
    int s = key.indexOf("{");
    if (s > -1) {
      int e = key.indexOf("}", s + 1);
      if (e > -1 && e != s + 1) {
        return key.substring(s + 1, e);
      }
    }
    return returnKeyOnAbsence ? key : null;
  }
}

转载于:https://my.oschina.net/u/3664884/blog/1821753

Spring Boot 中,我们可以通过添加 `spring-boot-starter-data-redis` 依赖来使用 Redis。然后,我们可以通过在 `application.properties` 或 `application.yml` 文件中添加以下属性来配置 Redis RDB 持久化: **application.properties:** ``` # Redis RDB 持久化 spring.redis.database=0 spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.timeout=3000 spring.redis.jedis.pool.max-active=8 spring.redis.jedis.pool.max-idle=8 spring.redis.jedis.pool.min-idle=0 spring.redis.jedis.pool.max-wait=-1 spring.redis.redis-cluster=false spring.redis.sentinel.master= spring.redis.sentinel.nodes= spring.redis.sentinel.password= spring.redis.sentinel.pool.max-active=8 spring.redis.sentinel.pool.max-idle=8 spring.redis.sentinel.pool.min-idle=0 spring.redis.sentinel.pool.max-wait=-1 spring.redis.sentinel.pool.master-name= spring.redis.sentinel.pool.nodes= spring.redis.sentinel.pool.password= spring.redis.cluster.max-redirects=3 spring.redis.cluster.nodes=redis://localhost:6379 spring.redis.cluster.password= spring.redis.cluster.timeout=3000 spring.redis.cluster.max-redirects=3 spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 spring.redis.lettuce.pool.max-wait=-1 spring.redis.lettuce.shutdown-timeout=100 spring.redis.lettuce.shutdown-timeout=100 ``` **application.yml:** ``` # Redis RDB 持久化 spring: redis: database: 0 host: localhost port: 6379 password: timeout: 3000 jedis: pool: max-active: 8 max-idle: 8 min-idle: 0 max-wait: -1 redis-cluster: false sentinel: master: nodes: password: pool: max-active: 8 max-idle: 8 min-idle: 0 max-wait: -1 pool: master-name: nodes: password: cluster: max-redirects: 3 nodes: redis://localhost:6379 password: timeout: 3000 max-redirects: 3 lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 max-wait: -1 shutdown-timeout: 100 shutdown-timeout: 100 ``` 其中,`spring.redis.database` 表示要使用的 Redis 数据库编号,默认为 0;`spring.redis.host` 和 `spring.redis.port` 表示 Redis 服务器的地址和端口号,默认为 `localhost` 和 `6379`;`spring.redis.password` 表示 Redis 认证密码,默认为空;`spring.redis.timeout` 表示连接 Redis 服务器的超时时间,默认为 3000 毫秒;`spring.redis.jedis.pool.max-active`、`spring.redis.jedis.pool.max-idle`、`spring.redis.jedis.pool.min-idle` 和 `spring.redis.jedis.pool.max-wait` 表示 Jedis 连接池的配置参数,可以根据实际情况进行调整。其他参数的含义可以参考官方文档。 配置完成后,我们可以通过在代码中注入 `RedisTemplate` 或 `StringRedisTemplate` 来进行 Redis 操作。例如: ``` @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } ``` 注意,在使用 Redis RDB 持久化时,我们需要在 Redis 服务器的配置文件中开启 RDB 持久化功能。可以通过在配置文件中添加以下内容来开启 RDB 持久化: ``` save 900 1 save 300 10 save 60 10000 ``` 其中,`save` 表示 RDB 持久化的配置项,后面的三个数字分别表示多长时间内有多少次修改操作就会触发一次 RDB 持久化。例如,上面的配置表示如果在 900 秒内有至少一次修改操作、或者在 300 秒内有至少 10 次修改操作、或者在 60 秒内有至少 10000 次修改操作,就会触发一次 RDB 持久化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值