1. redis 单例配置
-
配置文件
-
application.yml
spring: # redis redis: # Redis数据库索引(默认为0) database: 0 # Redis服务器地址 host: 127.0.0.1 # Redis服务器连接端口 port: 6379 # Redis服务器连接密码(默认为空) password: password # 连接超时时间(毫秒) timeout: 5000
-
redisson-single-config.yml
singleServerConfig: # 连接空闲超时,单位:毫秒 idleConnectionTimeout: 10000 pingTimeout: 1000 # 连接超时,单位:毫秒 connectTimeout: 10000 # 命令等待超时,单位:毫秒 timeout: 3000 # 命令失败重试次数,如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。 # 如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。 retryAttempts: 3 # 命令重试发送时间间隔,单位:毫秒 retryInterval: 1500 # 重新连接时间间隔,单位:毫 # 当与某个节点的连接断开时,等待与其重新建立连接的时间间隔 reconnectionTimeout: 3000 # 执行失败最大次数 failedAttempts: 3 # 密码 password: "password" # 单个连接最大订阅数量 subscriptionsPerConnection: 5 # 客户端名称 clientName: null # 节点地址 # 可以通过 host:port 的格式来指定节点地址 address: "redis://127.0.0.1:6379" # 发布和订阅连接的最小空闲连接数(长连接) subscriptionConnectionMinimumIdleSize: 1 # 发布和订阅连接池大小 subscriptionConnectionPoolSize: 50 # 发布和订阅连接的最小空闲连接数 connectionMinimumIdleSize: 32 # 连接池大小 connectionPoolSize: 64 # 数据库编号 database: 0 # 是否启用DNS监测 # dnsMonitoring: false # DNS监测时间间隔,单位:毫秒 dnsMonitoringInterval: 5000 # 线程池数量,默认值: 当前处理核数量 * 2 threads: 0 # Netty线程池数量,默认值: 当前处理核数量 * 2 nettyThreads: 0 # 编码 codec: !<org.redisson.codec.JsonJacksonCodec> {} # 传输模式 transportMode: "NIO"
-
-
配置类
RedissonConfig.java
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import java.io.IOException; /** * Redisson 配置类 * * @author sheng_zs@126.com * @date 2021-07-29 12:18 */ @Configuration public class RedissonConfig { @Bean public RedissonClient redissonClient() throws IOException { return Redisson.create(Config.fromYAML(new ClassPathResource("redisson-config.yml").getInputStream())); } }
-
工具类
RedisLock.java
,提供锁
import com.small.nine.exam.common.constant.RedisConstant; import org.redisson.api.RLock; import org.redisson.api.RReadWriteLock; import org.redisson.api.RedissonClient; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * Redisson 工具类 * * @author sheng_zs@126.com * @date 2021-07-29 14:08 */ // 懒加载 @Lazy @Component public class RedisLock { @Resource private RedissonClient redissonClient; /** * 返回 RLock 可重入锁 * * @param key redis key * @return {@link org.redisson.api.RLock} */ public RLock getRLock(String key) { return redissonClient.getLock(RedisConstant.REDISSON_LOCK_KEY + key); } /** * 返回 RLock 公平锁 * * @param key redis key * @return {@link org.redisson.api.RLock} */ public RLock getFairLock(String key) { return redissonClient.getFairLock(RedisConstant.REDISSON_LOCK_KEY + key); } /** * 读写锁,与 {@link java.util.concurrent.locks.ReentrantLock} 的读写锁效果一样 * * @param key redis key * @return {@link org.redisson.api.RReadWriteLock} */ public RReadWriteLock getReadWriteLock(String key) { return redissonClient.getReadWriteLock(RedisConstant.REDISSON_LOCK_KEY + key); } }
-
常用 API
// 获取 key 的可重入锁 RLock lock = redissonClient.getLock("key"); // 加锁,线程会一直等待,直到拿到该锁 // 具有 看门狗 自动延期机制,默认续30s,每隔30/3=10 秒续到30s void lock(); // 加锁,线程会一直等待,直到拿到该锁,然后 `var1 TimeUnit` 后自动解锁 // 不具有 看门狗 自动延期机制 void lock(long var1, TimeUnit var3) // 解锁,如果锁不是该线程持有则会抛出异常 void unlock(); // 强制解锁,即此锁不论是那个线程持有都会进行解锁 void forceUnlock(); // 尝试加锁 // 具有 看门狗 自动延期机制,默认续30s, boolean tryLock(); // 尝试加锁,立即返回加锁状态,如果加锁成功会在 `time TimeUnit` 后自动解锁 // 具有 看门狗 自动延期机制,默认续30s, boolean tryLock(long time, TimeUnit unit) // 尝试加锁,如果该锁被其他线程持有,会等待 var1 秒,然后返回是否成功,如果成功,会在 `var3 TimeUnit` 后自动解锁 // 具有 看门狗 自动延期机制,默认续30s, boolean tryLock(long var1, long var3, TimeUnit var5) // 检查该锁是否被任何线程所持有 boolean isLocked(); // 检查该锁是否当前线程持有 boolean isHeldByCurrentThread(); //当前线程对该锁的保持次数 int getHoldCount(); //该锁的剩余时间 long remainTimeToLive();
-
使用示例
@Resource private ValueOperations<String, Object> valueOperations; @Resource private RedisLock redisLock; @Override public String getAccessToken() { /* 1. 先获取 redis 上的 token */ Object o = valueOperations.get("access_token_key"); String token = ""; if (ObjectUtil.isNotNull(o) && StrUtil.isNotBlank(token = o.toString())) { return token; } // 获取 RLock 锁 RLock lock = redisLock.getRLock("lock:access_token_key"); // 不加时间,默认使用 看门狗 机制,默认续30s 每隔30/3=10 秒续到30s lock.lock(); try { // 防止不是第一个拿到 锁 o = valueOperations.get("access_token_key"); if (ObjectUtil.isNotNull(o) && StrUtil.isNotBlank(token = o.toString())) { return token; } // 强制刷新 access_token token = forceRefreshAccessToken(); } catch (Exception e) { log.error("获取 access_token 失败"); } finally { lock.unlock(); } return token; }
2. 集群配置
- 配置文件
-
application.yml
spring redis: database: 0 host: 127.0.0.1 port: 6379 password: password timeout: 5000 cluster: nodes: - 127.0.0.1:7000 - 127.0.0.1:7001 - 127.0.0.1:7002 - 127.0.0.1:7003 - 127.0.0.1:7004 - 127.0.0.1:7005
-
redisson-cluster-config.yml
clusterServersConfig: pingConnectionInterval: 30000 idleConnectionTimeout: 10000 pingTimeout: 1000 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 reconnectionTimeout: 3000 failedAttempts: 3 password: "password" subscriptionsPerConnection: 5 clientName: null loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {} slaveSubscriptionConnectionMinimumIdleSize: 1 slaveSubscriptionConnectionPoolSize: 50 slaveConnectionMinimumIdleSize: 32 slaveConnectionPoolSize: 64 masterConnectionMinimumIdleSize: 32 masterConnectionPoolSize: 64 readMode: "SLAVE" nodeAddresses: - "redis://127.0.0.1:7000" - "redis://127.0.0.1:7001" - "redis://127.0.0.1:7002" - "redis://127.0.0.1:7003" - "redis://127.0.0.1:7004" - "redis://127.0.0.1:7005" scanInterval: 1000 threads: 0 nettyThreads: 0 codec: !<org.redisson.codec.JsonJacksonCodec> {} transportMode: "NIO"
-