Redisson + Lettuce实现

Redis 之 客户端框架比较:Jedis,Redisson,Lettuce

三者区别参考:

Redis 客户端 Jedis、lettuce 和 Redisson 对比 - 程序员自由之路 - 博客园

Redis 之 客户端框架比较:Jedis,Redisson,Lettuce - 如梦灬遗忘 - 博客园

redis比较推荐用法是:Redisson + Lettuce

Redisson:主要用分布式锁

Lettuce:redis的基本功能,各种类型的数据类型的操作

依赖如下:

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

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>${redisson.version}</version>
</dependency>

实际使用过程中,只需要引入redisson依赖,因为它的依赖中已经包含了Lettuce,如下图:

 具体实现:

1.引入依赖

2.配置yaml文件

3.属性配置类

4.初始化RedissonClient客户端

5.初始化各种数据类型bean

6.工具类

1.引入依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>${redisson.version}</version>
</dependency>

2.配置yaml文件

spring
  redis:
    cluster:
      nodes: 192.168.106.27:8001,192.168.106.27:8002,192.168.106.27:8003,192.168.106.27:8004,192.168.106.27:8005,192.168.106.27:8006
      scan-interval: 1000
      retry-attempts: 3
      failed-attempts: 3
      slave-connection-pool-size: 64
      master-connection-pool-size: 64
      retry-interval: 1500
    password: 2021@zgzt
    timeout: 60000
    database: 0
    mode: cluster
    pool:
      max-idle: 16
      min-idle: 8
      max-active: 8
      max-wait: 3000
      conn-timeout: 3000
      so-timeout: 3000
      size: 10

3.属性配置类

@Component
@Data
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

    private int database;

    /**
     * 等待节点回复命令的时间。该时间从命令发送成功时开始计时
     */
    private int timeout;

    private String password;

    private String mode;

    /**
     * 池配置
     */
    private RedisPoolProperties pool;

    /**
     * 集群 信息配置
     */
    private RedisClusterProperties cluster;
}

@Data
public class RedisClusterProperties {

    /**
     * 集群状态扫描间隔时间,单位是毫秒
     */
    private int scanInterval;

    /**
     * 集群节点
     */
    private String nodes;

    /**
     * 默认值: SLAVE(只在从服务节点里读取)设置读取操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里读取。
     * MASTER - 只在主服务节点里读取。 MASTER_SLAVE - 在主从服务节点里都可以读取
     */
    private String readMode;
    /**
     * (从节点连接池大小) 默认值:64
     */
    private int slaveConnectionPoolSize;
    /**
     * 主节点连接池大小)默认值:64
     */
    private int masterConnectionPoolSize;

    /**
     * (命令失败重试次数) 默认值:3
     */
    private int retryAttempts;

    /**
     * 命令重试发送时间间隔,单位:毫秒 默认值:1500
     */
    private int retryInterval;

    /**
     * 执行失败最大次数默认值:3
     */
    private int failedAttempts;

}
@Data
public class RedisPoolProperties {

    private int maxIdle;

    private int minIdle;

    private int maxActive;

    private int maxWait;

    private int connTimeout;

    private int soTimeout;

    /**
     * 池大小
     */
    private int size;
}

 4.初始化RedissonClient客户端

@Configuration
public class RedissonConfig {

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public Redisson redisson() {
	//redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加
	List<String> clusterNodes = new ArrayList<>();
	String nodes = redisProperties.getCluster().getNodes();
	List<String> list = Arrays.asList(nodes.split(",")).stream().map(s -> (s.trim())).collect(Collectors.toList());

	for (int i = 0; i < list.size(); i++) {
	    clusterNodes.add("redis://" + list.get(i));
	}

	Config config = new Config();
	ClusterServersConfig clusterServersConfig = config.useClusterServers()
			.addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()]));
	clusterServersConfig.setPassword(redisProperties.getPassword());//设置密码
	return (Redisson) Redisson.create(config);
    }

    /**
     * 集群模式的 redisson 客户端
     *
     * @return
     */
    @Bean
    @ConditionalOnProperty(name = "spring.redis.mode", havingValue = "cluster")
    public RedissonClient redissonClient() {
	System.out.println("cluster redisProperties:" + redisProperties.getCluster());

	Config config = new Config();
	String[] nodes = redisProperties.getCluster().getNodes().split(",");
	List<String> newNodes = new ArrayList(nodes.length);
	Arrays.stream(nodes)
			.forEach((index) -> newNodes.add(index.startsWith("redis://") ? index : "redis://" + index));

	ClusterServersConfig serverConfig = config.useClusterServers().addNodeAddress(newNodes.toArray(new String[0]))
			.setScanInterval(redisProperties.getCluster().getScanInterval())
			.setIdleConnectionTimeout(redisProperties.getPool().getSoTimeout())
			.setConnectTimeout(redisProperties.getPool().getConnTimeout())
			.setRetryAttempts(redisProperties.getCluster().getRetryAttempts())
			.setRetryInterval(redisProperties.getCluster().getRetryInterval())
			.setMasterConnectionPoolSize(redisProperties.getCluster().getMasterConnectionPoolSize())
			.setSlaveConnectionPoolSize(redisProperties.getCluster().getSlaveConnectionPoolSize())
			.setTimeout(redisProperties.getTimeout());
	if (StringUtils.isNotBlank(redisProperties.getPassword())) {
	    serverConfig.setPassword(redisProperties.getPassword());
	}
	return Redisson.create(config);
    }

}

5.初始化各种数据类型bean

@Configuration
@Component
public class RedisConfig {

    @Resource
    private RedisConnectionFactory factory;

    public RedisConfig() {
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
	RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
	redisTemplate.setKeySerializer(new StringRedisSerializer());
	redisTemplate.setHashKeySerializer(new StringRedisSerializer());
	redisTemplate.setHashValueSerializer(new StringRedisSerializer());
	redisTemplate.setValueSerializer(new StringRedisSerializer());
	redisTemplate.setConnectionFactory(this.factory);
	return redisTemplate;
    }

    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
	return redisTemplate.opsForHash();
    }

    @Bean
    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
	return redisTemplate.opsForValue();
    }

    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
	return redisTemplate.opsForList();
    }

    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
	return redisTemplate.opsForSet();
    }

    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
	return redisTemplate.opsForZSet();
    }
}

6.工具类

@Component
public class RedisUtils {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private ValueOperations<String, String> valueOperations;
    @Resource
    private HashOperations<String, String, Object> hashOperations;
    @Resource
    private ListOperations<String, Object> listOperations;
    @Resource
    private SetOperations<String, Object> setOperations;
    @Resource
    private ZSetOperations<String, Object> zSetOperations;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public RedisUtils() {
    }

    public boolean exists(String key) {
	return this.redisTemplate.hasKey(key);
    }

    public void set(String key, Object value, long expire) {
	this.valueOperations.set(key, JsonUtils.toJson(value));
	if (expire != -1L) {
	    this.expire(key, expire, TimeUnit.SECONDS);
	}

    }

    public void set(String key, Object value) {
	this.set(key, value, -1L);
    }

    public void expire(String key, long time, TimeUnit timeUnit) {
	this.redisTemplate.expire(key, time, timeUnit);
    }

    public void expireKeyAt(String key, Date date) {
	this.redisTemplate.expireAt(key, date);
    }

    public long getKeyExpire(String key, TimeUnit timeUnit) {
	return this.redisTemplate.getExpire(key, timeUnit);
    }

    public void persistKey(String key) {
	this.redisTemplate.persist(key);
    }

    public <T> T get(String key, Class<T> clazz, long expire) {
	String value = (String) this.valueOperations.get(key);
	if (expire != -1L) {
	    this.expire(key, expire, TimeUnit.SECONDS);
	}

	return value == null ? null : JsonUtils.fromJson(value, clazz);
    }

    public JSONObject getJsonObject(String key, long expire) {
	String value = (String) this.valueOperations.get(key);
	if (expire != -1L) {
	    this.expire(key, expire, TimeUnit.SECONDS);
	}

	return value == null ? null : JsonUtils.fromJson(value);
    }

    public JSONArray getJsonArray(String key, long expire) {
	String value = (String) this.valueOperations.get(key);
	if (expire != -1L) {
	    this.expire(key, expire, TimeUnit.SECONDS);
	}

	return value == null ? null : JsonUtils.fromJsonArray(value);
    }

    public <T> T get(String key, Class<T> clazz) {
	return this.get(key, clazz, -1L);
    }

    public JSONObject getJsonObject(String key) {
	return this.getJsonObject(key, -1L);
    }

    public JSONArray getJsonArray(String key) {
	return this.getJsonArray(key, -1L);
    }

    public String get(String key, long expire) {
	String value = (String) this.valueOperations.get(key);
	if (expire != -1L) {
	    this.expire(key, expire, TimeUnit.SECONDS);
	}

	return value;
    }

    public Integer valueAppend(String key, String value) {
	return this.valueOperations.append(key, value);
    }

    public Double incrByDouble(String key, double increment) {
	return this.valueOperations.increment(key, increment);
    }

    public Long incrBy(String key, long increment) {
	return this.valueOperations.increment(key, increment);
    }

    public void setByMap(Map<String, String> valueMap) {
	this.valueOperations.multiSetIfAbsent(valueMap);
    }

    public void setMap(Map<String, String> valueMap) {
	this.valueOperations.multiSet(valueMap);
    }

    public Long getSize(String key) {
	return this.valueOperations.size(key);
    }

    public boolean setIfAbsent(String key, String value) {
	return this.valueOperations.setIfAbsent(key, value);
    }

    public boolean setIfAbsent(String key, String value, long l, TimeUnit timeUnit) {
	return this.valueOperations.setIfAbsent(key, value, l, timeUnit);
    }

    public boolean setIfPresent(String key, String value) {
	return this.valueOperations.setIfPresent(key, value);
    }

    public boolean setIfPresent(String key, String value, long l, TimeUnit timeUnit) {
	return this.valueOperations.setIfPresent(key, value, l, timeUnit);
    }

    public String get(String key) {
	return this.get(key, -1L);
    }

    public void delete(String key) {
	this.redisTemplate.delete(key);
    }

    public void delete(String... keys) {
	Set<String> kSet = (Set) Stream.of(keys).map((k) -> {
	    return k;
	}).collect(Collectors.toSet());
	this.redisTemplate.delete(kSet);
    }

    public void delete(Collection<String> keys) {
	Set<String> kSet = (Set) keys.stream().map((k) -> {
	    return k;
	}).collect(Collectors.toSet());
	this.redisTemplate.delete(kSet);
    }

    public void renameKey(String oldKey, String newKey) {
	this.redisTemplate.rename(oldKey, newKey);
    }

    public void setOperationsAdd(String key, Object value, long expire) {
	this.setOperations.add(key, new Object[] { value });
	if (expire != -1L) {
	    this.expire(key, expire, TimeUnit.SECONDS);
	}

    }

    public void setOperationsAdd(String key, Object value) {
	this.setOperationsAdd(key, value, -1L);
    }

    public Set setOperationsMembers(String key) {
	return this.setOperations.members(key);
    }

    public boolean setOperationsIsMembers(String key, Object value) {
	return this.setOperations.isMember(key, value);
    }

    public Long setOperationsRemove(String key, Object value) {
	return this.setOperations.remove(key, new Object[] { value });
    }

    public boolean hashKey(String key, String hashKey) {
	return this.hashOperations.hasKey(key, hashKey);
    }

    public void hashPut(String key, String hashKey, Object domain) {
	this.hashPutObject(key, hashKey, JsonUtils.toJson(domain));
    }

    public void hashPutObject(String key, String hashKey, Object domain) {
	this.hashOperations.put(key, hashKey, domain);
    }

    public Boolean hashPutIfAbsent(String key, String hashKey, String value) {
	return this.hashOperations.putIfAbsent(key, hashKey, value);
    }

    public void hPutAll(String key, Map<String, String> maps) {
	this.hashOperations.putAll(key, maps);
    }

    public Map<String, Object> hashTable(String key) {
	return this.hashOperations.entries(key);
    }

    public Object hashGet(String key, Object hashKey) {
	return this.hashOperations.get(key, hashKey);
    }

    public String hashGetString(String key, String hashKey) {
	Object object = this.hashGet(key, hashKey);
	return object == null ? null : object.toString();
    }

    public List<String> hmGetString(String key, Collection<String> hashKeys) {
	List<Object> values = this.hashOperations.multiGet(key, hashKeys);
	return null != values ?
			(List) values.stream().filter(Objects::nonNull).map(String::valueOf)
					.collect(Collectors.toList()) :
			Collections.emptyList();
    }

    public <T> T hashGetClass(String key, String hashKey, Class<T> clazz) {
	String value = this.hashGetString(key, hashKey);
	return value == null ? null : JsonUtils.fromJson(value, clazz);
    }

    public JSONObject hashGetJsonObject(String key, String hashKey) {
	String value = this.hashGetString(key, hashKey);
	return value == null ? null : JsonUtils.fromJson(value);
    }

    public Long hashDelete(String key, String... hashKey) {
	return this.hashOperations.delete(key, hashKey);
    }

    public long hashIncr(String key, String hashKey, long increment) {
	return this.hashOperations.increment(key, hashKey, increment);
    }

    public Double hashIncrByDouble(String key, String hashKey, double delta) {
	return this.hashOperations.increment(key, hashKey, delta);
    }

    public Long hashGetSize(String key) {
	return this.hashOperations.size(key);
    }

    public RedisTemplate<String, Object> getRedisTemplate() {
	return this.redisTemplate;
    }
}

思考:

1.上面代码有点多,既然是springBoot了,各种属性文件还需要配置吗,不是自动装配吗,但是没有找到属性文件

2.RedissonClinet需要自己初始化吗,应该需要的,但是看到其他项目并没有初始化动作,后续补充

猜你喜欢

转载自blog.csdn.net/C18298182575/article/details/120781970