当前位置:   article > 正文

Redis-redisson工具类使用和常用的锁功能_redissonclient的lock的工具类

redissonclient的lock的工具类

目录

简介

pom引入

yml

方法

自定义codec

工具类


简介

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它提供了一系列的分布式的Java常用对象,和许多分布式服务。

特点:

  • 支持 Redis 单节点(single)模式、哨兵(sentinel)模式、主从(Master/Slave)模式以及集群(Redis Cluster)模式
  • RMap中有一个功能是可以设置键值对的过期时间的,并可以注册键值对的事件监听器,但非实时性
  • 由Redisson默认的编码器为JsonJacksonCodec,JsonJackson在序列化有双向引用的对象时,会出现无限循环异常
    • 所以不用redission其他自带的二进制编码器,自行实现编码器(相互注入,用fastjson能 正常序列化到redis,而JsonJackson则抛出无限循环异常)
  • Redisson对订阅发布的封装是RTopic,在事件发布后,订阅方需要延时一下才能收到事件。
  • Redisson底层采用的是Netty 框架。支持Redis 2.8以上版本,支持Java1.6+以上版本

pom引入

  1. <!--redis依赖配置-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.redisson</groupId>
  8. <artifactId>redisson</artifactId>
  9. <version>3.15.0</version>
  10. </dependency>

yml

  1. spring:
  2. redis:
  3. database: 0 # Redis数据库索引(默认为0)
  4. port: 6379 # Redis服务器连接端口
  5. password: 123456 # Redis服务器连接密码(默认为空)
  6. jedis:
  7. pool:
  8. max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
  9. max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
  10. max-idle: 8 # 连接池中的最大空闲连接
  11. min-idle: 0 # 连接池中的最小空闲连接
  12. timeout: 3000ms # 连接超时时间(毫秒)
  13. host: aliyuncs.com # Redis服务器地址(单点配置)
  14. #sentinel: # 集群配置
  15. #master: master1
  16. #nodes: 172.16.33.216:16001,172.16.33.216:16002

方法

参考文档

  1. RLock rLock = redisson.getLock(KEY);
  2. // 最常见的使用方法
  3. rLock.lock();
  4. // 最长等待时间waitTime,最长持有锁的时间 holdTime, 第三个是单位
  5. rLock.tryLock(20, 15, TimeUnit.SECONDS)
  6. // 500s 后自动释放锁
  7. rLock.lock(500, TimeUnit.SECONDS);
  8. // 释放锁
  9. rLock.unlock();
  10. // 异步执行
  11. RLock lock = redisson.getLock("anyLock");
  12. lock.lockAsync();
  13. lock.lockAsync(10, TimeUnit.SECONDS);
  14. Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);
  15. // 分布式可重入公平锁(可异步执行,同上)
  16. RLock fairLock = redisson.getFairLock("anyLock");
  17. // 最常见的使用方法
  18. fairLock.lock();
  19. // 联锁
  20. RLock lock1 = redissonInstance1.getLock("lock1");
  21. RLock lock2 = redissonInstance2.getLock("lock2");
  22. RLock lock3 = redissonInstance3.getLock("lock3");
  23. RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
  24. // 同时加锁:lock1 lock2 lock3
  25. // 所有的锁都上锁成功才算成功。
  26. lock.lock();
  27. ...
  28. lock.unlock();
  29. // 读写锁,分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
  30. RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
  31. // 最常见的使用方法
  32. rwlock.readLock().lock();
  33. //
  34. rwlock.writeLock().lock();

自定义codec

Redisson提供的几种数据序列化对象编码应用:https://github.com/redisson/redisson/wiki/4.-%E6%95%B0%E6%8D%AE%E5%BA%8F%E5%88%97%E5%8C%96

想自定义codec,需要自己初始化redissonClient,再调用Redisson.create(config),而通过 redissonClient.getConfig().setCodec(...)是无效的

  1. config.setCodec(new FastJsonCodec());
  2. redisson = Redisson.create(config);

 FastJsonCodec.java

  1. import com.alibaba.fastjson.JSON;
  2. import com.alibaba.fastjson.serializer.SerializerFeature;
  3. import io.netty.buffer.ByteBufInputStream;
  4. import io.netty.buffer.ByteBufOutputStream;
  5. import org.redisson.client.codec.BaseCodec;
  6. import io.netty.buffer.ByteBuf;
  7. import io.netty.buffer.ByteBufAllocator;
  8. import org.redisson.client.protocol.Decoder;
  9. import org.redisson.client.protocol.Encoder;
  10. import java.io.IOException;
  11. /**
  12. * @Author: s
  13. * @Date: 2021/4/20 22:32
  14. */
  15. public class FastJsonCodec extends BaseCodec {
  16. private final Encoder encoder = in -> {
  17. ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
  18. try {
  19. ByteBufOutputStream os = new ByteBufOutputStream(out);
  20. JSON.writeJSONString(os, in, SerializerFeature.WriteClassName);
  21. return os.buffer();
  22. } catch (IOException e) {
  23. out.release();
  24. throw e;
  25. } catch (Exception e) {
  26. out.release();
  27. throw new IOException(e);
  28. }
  29. };
  30. private final Decoder<Object> decoder = (buf, state) -> JSON.parseObject(new ByteBufInputStream(buf), Object.class);
  31. @Override
  32. public Decoder<Object> getValueDecoder() {
  33. return decoder;
  34. }
  35. @Override
  36. public Encoder getValueEncoder() {
  37. return encoder;
  38. }
  39. }

工具类

  1. import org.redisson.Redisson;
  2. import org.redisson.api.RBucket;
  3. import org.redisson.api.RList;
  4. import org.redisson.api.RLock;
  5. import org.redisson.api.RMapCache;
  6. import org.redisson.api.RScoredSortedSet;
  7. import org.redisson.api.RSet;
  8. import org.redisson.api.RedissonClient;
  9. import org.redisson.client.codec.StringCodec;
  10. import org.redisson.config.Config;
  11. import org.slf4j.Logger;
  12. import org.slf4j.LoggerFactory;
  13. import org.springframework.beans.factory.annotation.Value;
  14. import org.springframework.context.annotation.Configuration;
  15. import javax.annotation.PostConstruct;
  16. import javax.annotation.PreDestroy;
  17. import java.io.IOException;
  18. import java.util.concurrent.TimeUnit;
  19. /**
  20. * @author
  21. * @version
  22. */
  23. @Configuration
  24. public class RedissonCache {
  25. private Logger logger = LoggerFactory.getLogger(getClass());
  26. /**
  27. * 默认缓存时间
  28. */
  29. private static final Long DEFAULT_EXPIRED = 5 * 60L;
  30. /**
  31. * redis key前缀
  32. */
  33. private static final String REDIS_KEY_PREFIX = "";
  34. /**
  35. * redisson client对象
  36. */
  37. private RedissonClient redisson;
  38. /**
  39. * redis host
  40. */
  41. @Value("${spring.redis.host}")
  42. private String host;
  43. /**
  44. * redis password
  45. */
  46. @Value("${spring.redis.password}")
  47. private String password;
  48. @Value("${spring.redis.port}")
  49. private Integer port;
  50. /**
  51. * 连接超时时间
  52. */
  53. private Integer connectTimeout = 3000;
  54. /**
  55. * 初始化连接
  56. *
  57. * @throws IOException
  58. */
  59. @PostConstruct
  60. public void init() throws IOException {
  61. Config config = new Config();
  62. config.useSingleServer()
  63. .setAddress("redis://"+ host+":"+port)
  64. .setPassword(password)
  65. .setDatabase(0)
  66. .setPingTimeout(3000)
  67. .setTimeout(5000)
  68. .setSubscriptionConnectionMinimumIdleSize(1)
  69. .setSubscriptionConnectionPoolSize(256)
  70. .setConnectTimeout(connectTimeout)
  71. .setConnectionPoolSize(256)
  72. .setConnectionMinimumIdleSize(1)
  73. .setRetryAttempts(3)
  74. .setRetryInterval(3000)
  75. .setIdleConnectionTimeout(30000)
  76. .setClientName("com.meiguang.mgframework.extend.redis.RedisCache");
  77. if (redisson == null) {
  78. redisson = Redisson.create(config);
  79. logger.info( "redis连接成功,server={}", host);
  80. } else {
  81. logger.warn("redis 重复连接,config={}", config);
  82. }
  83. }
  84. /**
  85. * 读取缓存
  86. *
  87. * @param key 缓存key
  88. * @param <T>
  89. * @return 缓存返回值
  90. */
  91. public <T> T get(String key) {
  92. RBucket<T> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key);
  93. return bucket.get();
  94. }
  95. /**
  96. * 以string的方式读取缓存
  97. *
  98. * @param key 缓存key
  99. * @return 缓存返回值
  100. */
  101. public String getString(String key) {
  102. RBucket<String> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key, StringCodec.INSTANCE);
  103. return bucket.get();
  104. }
  105. /**
  106. * 设置缓存(注:redisson会自动选择序列化反序列化方式)
  107. *
  108. * @param key 缓存key
  109. * @param value 缓存值
  110. * @param <T>
  111. */
  112. public <T> void put(String key, T value) {
  113. RBucket<T> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key);
  114. bucket.set(value, DEFAULT_EXPIRED, TimeUnit.SECONDS);
  115. }
  116. /**
  117. * 以string的方式设置缓存
  118. *
  119. * @param key
  120. * @param value
  121. */
  122. public void putString(String key, String value) {
  123. RBucket<String> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key, StringCodec.INSTANCE);
  124. bucket.set(value, DEFAULT_EXPIRED, TimeUnit.SECONDS);
  125. }
  126. /**
  127. * 以string的方式保存缓存(与其他应用共用redis时需要使用该函数)
  128. *
  129. * @param key 缓存key
  130. * @param value 缓存值
  131. * @param expired 缓存过期时间
  132. */
  133. public void putString(String key, String value, long expired) {
  134. RBucket<String> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key, StringCodec.INSTANCE);
  135. bucket.set(value, expired <= 0 ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
  136. }
  137. /**
  138. * 如果不存在则写入缓存(string方式,不带有redisson的格式信息)
  139. *
  140. * @param key 缓存key
  141. * @param value 缓存值
  142. * @param expired 缓存过期时间
  143. */
  144. public boolean putStringIfAbsent(String key, String value, long expired) {
  145. RBucket<String> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key, StringCodec.INSTANCE);
  146. return bucket.trySet(value, expired <= 0 ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
  147. }
  148. /**
  149. * 如果不存在则写入缓存(string方式,不带有redisson的格式信息)(不带过期时间,永久保存)
  150. *
  151. * @param key 缓存key
  152. * @param value 缓存值
  153. */
  154. public boolean putStringIfAbsent(String key, String value) {
  155. RBucket<String> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key, StringCodec.INSTANCE);
  156. return bucket.trySet(value);
  157. }
  158. /**
  159. * 设置缓存
  160. *
  161. * @param key 缓存key
  162. * @param value 缓存值
  163. * @param expired 缓存过期时间
  164. * @param <T> 类型
  165. */
  166. public <T> void put(String key, T value, long expired) {
  167. RBucket<T> bucket = redisson.getBucket(REDIS_KEY_PREFIX + key);
  168. bucket.set(value, expired <= 0 ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
  169. }
  170. /**
  171. * 移除缓存
  172. *
  173. * @param key
  174. */
  175. public void remove(String key) {
  176. redisson.getBucket(REDIS_KEY_PREFIX + key).delete();
  177. }
  178. /**
  179. * 判断缓存是否存在
  180. *
  181. * @param key
  182. * @return
  183. */
  184. public boolean exists(String key) {
  185. return redisson.getBucket(REDIS_KEY_PREFIX + key).isExists();
  186. }
  187. /**
  188. * 暴露redisson的RList对象
  189. *
  190. * @param key
  191. * @param <T>
  192. * @return
  193. */
  194. public <T> RList<T> getRedisList(String key) {
  195. return redisson.getList(REDIS_KEY_PREFIX + key);
  196. }
  197. /**
  198. * 暴露redisson的RMapCache对象
  199. *
  200. * @param key
  201. * @param <K>
  202. * @param <V>
  203. * @return
  204. */
  205. public <K, V> RMapCache<K, V> getRedisMap(String key) {
  206. return redisson.getMapCache(REDIS_KEY_PREFIX + key);
  207. }
  208. /**
  209. * 暴露redisson的RSET对象
  210. *
  211. * @param key
  212. * @param <T>
  213. * @return
  214. */
  215. public <T> RSet<T> getRedisSet(String key) {
  216. return redisson.getSet(REDIS_KEY_PREFIX + key);
  217. }
  218. /**
  219. * 暴露redisson的RScoredSortedSet对象
  220. *
  221. * @param key
  222. * @param <T>
  223. * @return
  224. */
  225. public <T> RScoredSortedSet<T> getRedisScoredSortedSet(String key) {
  226. return redisson.getScoredSortedSet(REDIS_KEY_PREFIX + key);
  227. }
  228. /**
  229. * 暴露redisson的Lock对象
  230. *
  231. * @param key
  232. * @return
  233. */
  234. public RLock getRedisLock(String key) {
  235. return redisson.getLock(REDIS_KEY_PREFIX + key);
  236. }
  237. @PreDestroy
  238. public void close() {
  239. try {
  240. if (redisson != null) {
  241. redisson.shutdown();
  242. }
  243. } catch (Exception ex) {
  244. logger.error( ex.getMessage(), ex);
  245. }
  246. }
  247. /**
  248. * Setter method for property <tt>host</tt>.
  249. *
  250. * @param host value to be assigned to property host
  251. */
  252. public void setHost(String host) {
  253. this.host = host;
  254. }
  255. /**
  256. * Setter method for property <tt>password</tt>.
  257. *
  258. * @param password value to be assigned to property password
  259. */
  260. public void setPassword(String password) {
  261. this.password = password;
  262. }
  263. /**
  264. * Setter method for property <tt>connectTimeout</tt>.
  265. *
  266. * @param connectTimeout value to be assigned to property connectTimeout
  267. */
  268. public void setConnectTimeout(Integer connectTimeout) {
  269. this.connectTimeout = connectTimeout;
  270. }
  271. }

额外功能:https://github.com/redisson/redisson/wiki/10.-%E9%A2%9D%E5%A4%96%E5%8A%9F%E8%83%BD

包括对Redis节点的操作(连接或断开),命令的批量执行以及配置事务属性

其他文章:synchronized、Lock和 redis锁,基于redis实现的扣减库存锁(附代码)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/125823
推荐阅读
相关标签
  

闽ICP备14008679号