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需要自己初始化吗,应该需要的,但是看到其他项目并没有初始化动作,后续补充