中间件 | Redis - [包 & 工具]

@

§1 集成 cluster 工具

  • 老版本 redis 想搭建集群需要安装 ruby 环境,5 以后版本将 reis-trib.rb 集成进 reis-cli
  • redis-benchmark 工具支持集群,可以对多分片进行压测

§2 Jedis

  • api 相对友好,基本与命名同名
  • jedis 线程不安全,尽量使用连接池,避免使用单例
    虽然 redis 单线程,但多线程复用 jedis 时,会导致多线程复用 jedis 打开的 socket,导致将 命令1 的响应作为 命令2 的返回的现象

依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.6.0</version>
</dependency>

配置
线程不安全,正常情况现用现开,或使用连接池

@Configuration
public class JedisConfig {
    @Bean
    public Jedis jedis(){
        return new Jedis("192.168.3.11",6379);
    }
}

防火墙
无法连接时,查看防火墙相关配置,参考 firewall-cmd 指令

查看端口是否开启
firewall-cmd --query-port=6381/tcp

在防火墙配置端口
firewall-cmd --add-port=6381/tcp --permanent

刷新防火墙
firewall-cmd --reload

使用示例
key 相关

public void key(){
    jedis.set("k","value");
    jedis.mset("k1","v1","k2","v2");

    String value = jedis.get("k");

    Long success = jedis.expire("k",10L);

    Long ttl = jedis.ttl("k");

    Set<String> keys = jedis.keys("*");
}

list 相关

public void list(){
    jedis.lpush("key1","1","2","3");
    List<String> pops = jedis.lpop("key1",1);
    List<String> ranges = jedis.lrange("key1",0,-1);
}

集群操作

// 去中心化的集群,可以任选一个主机
HostAndPort hostAndPort = new HostAndPort("192.168.3.11",6379);
JedisCluster jedisCluster = new JedisCluster(hostAndPort);

jedisCluster.set("key","value");

§3 JedisPool

依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.6.0</version>
</dependency>

配置

private static JedisSentinelPool jedisSentinelPool = null;

public static Jedis getJedisFromSentinel(){
	if(jedisSentinelPool == null){
		Set<String> sentinelSet = new HashSet<>();
		sentinelSet.add("192.168.3.11:26379");

		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		// 最大 Jedis 实例数
		jedisPoolConfig.setMaxTotal(1000);
		// 池中空闲 Jedis 实例的最大数量,多余此数量的空闲示例浪费
		jedisPoolConfig.setMaxIdle(64);
		// 池中空闲 Jedis 实例的最小数量,少于此数量的空闲示例认为不安全,可能随时扩容
		jedisPoolConfig.setMinIdle(8);
		// 连接池耗尽时是否阻塞(以等待释放)
		jedisPoolConfig.setBlockWhenExhausted(true);
		// 最大等待时间
		jedisPoolConfig.setMaxWaitMillis(60 * 1000);
		// 新创建的 Jedis 是否测试连通性,即 ping()
		jedisPoolConfig.setTestOnBorrow(true);

		jedisSentinelPool = new JeisSentinelPool("$监控对象别名$",sentinelSet,jedisPoolConfig);
	}

	return jedisSentinelPool.getResource();
}

§4 Redisson

  • 自带分布式锁,可以满足一般场景,比如
  • api 相对不友好

Lettuce 香菜 redis 连接池

部分代码

@Bean
public RedisTemplate<String, Serializable> redis(LettuceConnectionFactory connectionFactory){
    RedisTemplate<String,Serializable> redis = new RedisTemplate<>();
    redis.setConnectionFactory(connectionFactory)
    ;
    redis.setKeySerializer(new StringRedisSerializer());
    redis.setValueSerializer(new GenericJackson2JsonRedisSerializer());

    return redis;
}

§5 spring-boot-starter-data-redis

依赖
在 springboot 中使用 redis 需要引入下面依赖

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

同时需要增加对象池的支持

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-pool2</artifactId>
   <version>2.4.2</version>
</dependency>

如果需要按下文 配置,需要追加下面的依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.10</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.10</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.10</version>
</dependency>

yml

spring:
  redis:
    host: 192.168.3.11
    port: 6379
    database: 0
    timeout: 1800000
    lettuce:
      pool:
        max-active: 20
        max-wait: 1
        max-idle: 20
        min-idle: 0

配置

@EnableCaching
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> redis = new RedisTemplate<>();

        Jackson2JsonRedisSerializer valueSerializer = createJackson2JsonRedisSerializer();

        redis.setConnectionFactory(factory);
        redis.setKeySerializer(new StringRedisSerializer());
        redis.setValueSerializer(valueSerializer);
        redis.setHashValueSerializer(valueSerializer);
        return redis;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory){
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(createJackson2JsonRedisSerializer()))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config).build();

        return cacheManager;
    }

    private Jackson2JsonRedisSerializer createJackson2JsonRedisSerializer() {
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer(Object.class);
        valueSerializer.setObjectMapper(om);
        return valueSerializer;
    }
}

使用示例
key 相关

redis.opsForValue().set("key","value");
Object value = redis.opsForValue().get("key");
posted @ 2025-05-20 14:47  问仙长何方蓬莱  阅读(12)  评论(0)    收藏  举报