@@ -266,5 +266,293 @@ B~~~~~B~~~~~B~~~~~B~~~~~~~~~~~B |
266
266
LFU把原先的key对象内部的24位时钟分为了两个部分,前16位还代表时钟,后8位代表一个计数器。
267
267
使用LFU淘汰时,会根据计数器中key使用的频率精准的淘汰最少使用频率的key。
268
268
269
-
270
269
------------
270
+
271
+ ### SpringBoot集成Redisson框架-实现Redis调用
272
+
273
+ ##### 1、添加Redisson的Maven依赖
274
+ ``` java
275
+ < ! -- https: // mvnrepository.com/artifact/org.redisson/redisson -->
276
+ < dependency>
277
+ < groupId> org. redisson< / groupId>
278
+ < artifactId> redisson< / artifactId>
279
+ < version> 3.5 . 0 < / version>
280
+ < / dependency>
281
+ ```
282
+
283
+ ##### 2、在application.properties配置文件中添加Redisson配置
284
+ ``` java
285
+ #redis链接地址
286
+ spring. redisson. address= redis: // 10.211.55.6:6379
287
+ #当前处理核数量 * 2
288
+ spring. redisson. thread= 4
289
+ #指定编解码
290
+ spring. redisson. codec= org.redisson.codec. JsonJacksonCodec ;
291
+ #最小空闲连接数,默认值: 10 ,最小保持连接数(长连接)
292
+ spring. redisson. connectionMinimumIdleSize= 12
293
+ #连接空闲超时,单位:毫秒 默认10000 ;当前连接池里的连接数量超过了最小空闲连接数,
294
+ #而连接空闲时间超过了该数值,这些连接将会自动被关闭,并从连接池里去掉
295
+ spring. redisson. idleConnectionTimeout= 10000
296
+ #ping节点超时,单位:毫秒,默认1000
297
+ spring. redisson. pingTimeout= 1000
298
+ #连接等待超时,单位:毫秒,默认10000
299
+ spring. redisson. connectTimeout= 10000
300
+ #命令等待超时,单位:毫秒,默认3000 ;等待节点回复命令的时间。该时间从命令发送成功时开始计时
301
+ spring. redisson. timeout= 3000
302
+ #命令失败重试次数,默认值: 3
303
+ spring. redisson. retryAttempts= 2
304
+ #命令重试发送时间间隔,单位:毫秒,默认值: 1500
305
+ spring. redisson. retryInterval= 1500
306
+ #重新连接时间间隔,单位:毫秒,默认值:3000 ;连接断开时,等待与其重新建立连接的时间间隔
307
+ spring. redisson. reconnectionTimeout= 3000
308
+ #执行失败最大次数, 默认值:3 ;失败后直到 reconnectionTimeout超时以后再次尝试。
309
+ spring. redisson. failedAttempts= 2
310
+ #身份验证密码
311
+ #spring. redisson. password=
312
+ #单个连接最大订阅数量,默认值:5
313
+ spring. redisson. subscriptionsPerConnection= 5
314
+ #客户端名称
315
+ #spring. redisson. clientName=
316
+ #发布和订阅连接的最小空闲连接数,默认值:1 ;Redisson 内部经常通过发布和订阅来实现许多功能。
317
+ #长期保持一定数量的发布订阅连接是必须的
318
+ spring. redisson. subscriptionConnectionMinimumIdleSize= 1
319
+ #发布和订阅连接池大小,默认值:50
320
+ spring. redisson. subscriptionConnectionPoolSize= 50
321
+ #连接池最大容量。默认值:64 ;连接池的连接数量自动弹性伸缩
322
+ spring. redisson. connectionPoolSize= 64
323
+ #数据库编号,默认值:0
324
+ spring. redisson. database= 0
325
+ #是否启用DNS 监测,默认值:false
326
+ spring. redisson. dnsMonitoring= false
327
+ #DNS 监测时间间隔,单位:毫秒,默认值:5000
328
+ spring. redisson. dnsMonitoringInterval= 5000
329
+ ```
330
+
331
+ ##### 3、配置RedissonCofnig的Bean
332
+ ``` java
333
+ @Configuration
334
+ @ConfigurationProperties (prefix = " spring.redisson" )
335
+ @Setter
336
+ @Getter
337
+ public class RedissonConfig {
338
+
339
+ // redis链接地址
340
+ private String address;
341
+ // 最小空闲连接数,默认值:10,最小保持连接数(长连接)
342
+ private int connectionMinimumIdleSize;
343
+ // 连接空闲超时,单位:毫秒 默认10000;当前连接池里的连接数量超过了最小空闲连接数,
344
+ // 而连接空闲时间超过了该数值,这些连接将会自动被关闭,并从连接池里去掉
345
+ private int idleConnectionTimeout;
346
+ // ping节点超时,单位:毫秒,默认1000
347
+ private int pingTimeout;
348
+ // 连接等待超时,单位:毫秒,默认10000
349
+ private int connectTimeout;
350
+ // 命令等待超时,单位:毫秒,默认3000;等待节点回复命令的时间。该时间从命令发送成功时开始计时
351
+ private int timeout;
352
+ // 命令失败重试次数,默认值:3
353
+ private int retryAttempts;
354
+ // 命令重试发送时间间隔,单位:毫秒,默认值:1500
355
+ private int retryInterval;
356
+ // 重新连接时间间隔,单位:毫秒,默认值:3000;连接断开时,等待与其重新建立连接的时间间隔
357
+ private int reconnectionTimeout;
358
+ // 执行失败最大次数, 默认值:3;失败后直到 reconnectionTimeout超时以后再次尝试。
359
+ private int failedAttempts;
360
+ // 身份验证密码
361
+ private String password;
362
+ // 单个连接最大订阅数量,默认值:5
363
+ private int subscriptionsPerConnection;
364
+ // 客户端名称
365
+ private String clientName;
366
+ // 长期保持一定数量的发布订阅连接是必须的
367
+ private int subscriptionConnectionMinimumIdleSize;
368
+ // 发布和订阅连接池大小,默认值:50
369
+ private int subscriptionConnectionPoolSize;
370
+ // 发布和订阅连接池大小,默认值:50
371
+ private int connectionPoolSize;
372
+ // 数据库编号,默认值:0
373
+ private int database;
374
+ // 是否启用DNS监测,默认值:false
375
+ private boolean dnsMonitoring;
376
+ // DNS监测时间间隔,单位:毫秒,默认值:5000
377
+ private int dnsMonitoringInterval;
378
+ // 当前处理核数量 * 2
379
+ private int thread;
380
+
381
+ @Bean
382
+ public RedissonClient redisson () throws Exception {
383
+ System . out. println(address);
384
+ Config config = new Config ();
385
+ config. useSingleServer()
386
+ .setAddress(address)
387
+ .setConnectionMinimumIdleSize(connectionMinimumIdleSize)
388
+ .setConnectionPoolSize(connectionPoolSize)
389
+ .setDatabase(database)
390
+ .setDnsMonitoring(dnsMonitoring)
391
+ .setDnsMonitoringInterval(dnsMonitoringInterval)
392
+ .setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize)
393
+ .setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize)
394
+ .setSubscriptionsPerConnection(subscriptionsPerConnection)
395
+ .setClientName(clientName)
396
+ .setFailedAttempts(failedAttempts)
397
+ .setRetryAttempts(retryAttempts)
398
+ .setRetryInterval(retryInterval)
399
+ .setReconnectionTimeout(reconnectionTimeout)
400
+ .setTimeout(timeout)
401
+ .setConnectTimeout(connectTimeout)
402
+ .setIdleConnectionTimeout(idleConnectionTimeout)
403
+ .setPingTimeout(pingTimeout)
404
+ .setPassword(password);
405
+
406
+ return Redisson . create(config);
407
+ }
408
+ }
409
+ ```
410
+
411
+ ##### 5、使用 RLock 实现 Redis 分布式锁
412
+ ``` java
413
+ /**
414
+ * 使用 RLock 实现 Redis 分布式锁
415
+ * RLock 是 Java 中可重入锁的分布式实现
416
+ */
417
+ @SneakyThrows
418
+ public void lock() {
419
+ // RLock 继承了 java.util.concurrent.locks.Lock 接口
420
+ RLock lock = redissonClient. getLock(" lock" );
421
+ lock. lock();
422
+ System . out. println(" lock acquired" );
423
+
424
+ Thread t = new Thread (() - > {
425
+ RLock lock1 = redissonClient. getLock(" lock" );
426
+ lock1. lock();
427
+ System . out. println(" lock acquired by thread" );
428
+ lock1. unlock();
429
+ System . out. println(" lock released by thread" );
430
+ });
431
+ t. start();
432
+
433
+ System . out. println(" lock sleep begin" );
434
+ Thread . sleep(1000 );
435
+ System . out. println(" lock sleep end" );
436
+
437
+ lock. unlock();
438
+ System . out. println(" lock released" );
439
+
440
+ t. join();
441
+ }
442
+ ```
443
+
444
+ ##### 6、使用 RAtomicLong 实现 Redis 分布式原子操作
445
+ ``` java
446
+ /**
447
+ * 使用 RAtomicLong 实现 Redis 分布式原子操作
448
+ */
449
+ @SneakyThrows
450
+ public void atomicLong() {
451
+ RAtomicLong atomicLong = redissonClient. getAtomicLong(" atomicLong" );
452
+ System . out. println(" Init value: " + atomicLong. get());
453
+
454
+ atomicLong. incrementAndGet();
455
+ System . out. println(" Current value: " + atomicLong. get());
456
+
457
+ atomicLong. addAndGet(1L );
458
+ System . out. println(" Final value: " + atomicLong. get());
459
+ }
460
+ ```
461
+
462
+ ##### 7、基于 Redis 的 Redisson 分布式列表(list)结构的 RList
463
+ ``` java
464
+ /**
465
+ * 基于 Redis 的 Redisson 分布式列表(list)结构的 RList
466
+ * Java对象实现了 java.util.list 接口的同时,确保了元素插入时的顺序
467
+ * 对象的最大容容量受 Redis 限制,最大数量是 4294967295 个
468
+ */
469
+ @SneakyThrows
470
+ public void list() {
471
+ RList<String > list = redissonClient. getList(" list" );
472
+ list. add(" ip" );
473
+ list. add(" man" );
474
+ list. add(" ipman" );
475
+ list. remove(- 1 );
476
+
477
+ boolean contains = list. contains(" ipman" );
478
+ System . out. println(" List size: " + list. size());
479
+ System . out. println(" Is list contains name 'ipman': " + contains);
480
+ list. forEach(System . out:: println);
481
+ }
482
+ ```
483
+
484
+ ##### 8、基于 Redis 的 Redisson 的分布式映射结构的 RMap
485
+ ``` java
486
+ /**
487
+ * 基于 Redis 的 Redisson 的分布式映射结构的 RMap
488
+ * Java对象实现了 java.util.concurrent.ConcurrentMap 接口和 java.util.Map 接口
489
+ * 与HashMap不同的是,RMap保持了元素的插入顺序,该对象的最大容量是 4294967295 个
490
+ */
491
+ @SneakyThrows
492
+ public void map() {
493
+ RMap<String , String > map = redissonClient. getMap(" map" );
494
+ String prevVal = map. put(" man" , " 2" );
495
+ // key 空闲时写入
496
+ String currentVal = map. putIfAbsent(" ipman" , " 3" );
497
+ // 在 Map 头部写入key
498
+ map. fastPut(" ip" , " 1" );
499
+ printMap(map);
500
+
501
+ // 异步的方式获取
502
+ RFuture<String > futurePut = map. putAsync(" ipman" , " 4" );
503
+ RFuture<String > futureGet = map. getAsync(" ipman" );
504
+ System . out. println(" Map async put:" + futurePut. get());
505
+ System . out. println(" Map async get:" + futureGet. get());
506
+
507
+ // 阻塞等待
508
+ int count = 6 ;
509
+ CountDownLatch latch = new CountDownLatch (count);
510
+
511
+ // Map 对象锁,先获取锁,才能操作 Map 集合
512
+ String k = " mapLock" ;
513
+ for (int i = 0 ; i < count / 2 ; i++ ) {
514
+ Thread t = new Thread (() - > {
515
+ RLock keyLock = map. getLock(k);
516
+ keyLock. lock();
517
+ try {
518
+ String v = map. get(" ipman" );
519
+ System . out. println(" Map lock get:" + v + " t:" + Thread . currentThread(). getName());
520
+ // 其他业务逻辑
521
+ } finally {
522
+ keyLock. unlock();
523
+ latch. countDown();
524
+ }
525
+ });
526
+ t. setName(" thread-" + i);
527
+ t. start();
528
+ }
529
+
530
+ // Map 读写锁,读时不能写
531
+ for (int i = 0 ; i < count / 2 ; i++ ) {
532
+ Thread t = new Thread (() - > {
533
+ RReadWriteLock rwLock = map. getReadWriteLock(k);
534
+ rwLock. readLock(). lock();
535
+ try {
536
+ String v = map. get(" ipman" );
537
+ System . out. println(" Map read write lock get:" + v + " t:" + Thread . currentThread(). getName());
538
+ // 其他业务逻辑
539
+ } finally {
540
+ rwLock. readLock(). unlock();
541
+ latch. countDown();
542
+ }
543
+ });
544
+ t. setName(" thread-" + i);
545
+ t. start();
546
+ }
547
+
548
+ latch. await();
549
+ }
550
+
551
+
552
+ public static void printMap(Map<String , String > map) {
553
+ Set<Map .Entry<String , String > > ms = map. entrySet();
554
+ for (Map . Entry<String , String > entry : ms) {
555
+ System . out. println(" Map key:" + entry. getKey() + " val:" + entry. getValue());
556
+ }
557
+ }
558
+ ```
0 commit comments