<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Boot + Redis 實現(xiàn)各種操作,寫得太好了吧!

          共 13054字,需瀏覽 27分鐘

           ·

          2021-11-06 12:35

          https://blog.csdn.net/qq_42105629/article/details/102589319

          一、Jedis,Redisson,Lettuce 三者的區(qū)別

          共同點:都提供了基于 Redis 操作的 Java API,只是封裝程度,具體實現(xiàn)稍有不同。

          不同點:

          • 1.1、Jedis

          是 Redis 的 Java 實現(xiàn)的客戶端。支持基本的數(shù)據(jù)類型如:String、Hash、List、Set、Sorted Set。

          特點:使用阻塞的 I/O,方法調(diào)用同步,程序流需要等到 socket 處理完 I/O 才能執(zhí)行,不支持異步操作。Jedis 客戶端實例不是線程安全的,需要通過連接池來使用 Jedis。

          • 1.1、Redisson

          優(yōu)點點:分布式鎖,分布式集合,可通過 Redis 支持延遲隊列。

          • 1.3、 Lettuce

          用于線程安全同步,異步和響應使用,支持集群,Sentinel,管道和編碼器。

          基于 Netty 框架的事件驅(qū)動的通信層,其方法調(diào)用是異步的。Lettuce 的 API 是線程安全的,所以可以操作單個 Lettuce 連接來完成各種操作。

          二、Jedis

          三、RedisTemplate

          3.1、使用配置

          maven 配置引入,(要加上版本號,我這里是因為 Parent 已聲明)

             
          org.springframework.boot
          spring-boot-starter-data-redis



          application-dev.yml

          spring:
          redis:
          host: 192.168.1.140
          port: 6379
          password:
          database: 15 # 指定redis的分庫(共16015

          3.2、使用示例

           @Resource
          private StringRedisTemplate stringRedisTemplate;

          @Override
          public CustomersEntity findById(Integer id) {
          // 需要緩存
          // 所有涉及的緩存都需要刪除,或者更新
          try {
          String toString = stringRedisTemplate.opsForHash().get(REDIS_CUSTOMERS_ONE, id + "").toString();
          if (toString != null) {
          return JSONUtil.toBean(toString, CustomersEntity.class);
          }
          } catch (Exception e) {
          e.printStackTrace();
          }
          // 緩存為空的時候,先查,然后緩存redis
          Optional byId = customerRepo.findById(id);
          if (byId.isPresent()) {
          CustomersEntity customersEntity = byId.get();
          try {
          stringRedisTemplate.opsForHash().put(REDIS_CUSTOMERS_ONE, id + "", JSONUtil.toJsonStr(customersEntity));
          } catch (Exception e) {
          e.printStackTrace();
          }
          return customersEntity;
          }
          return null;
          }

          3.3、擴展

          3.3.1、spring-boot-starter-data-redis 的依賴包

          3.3.2、stringRedisTemplate API(部分展示)

          opsForHash --> hash 操作
          opsForList --> list 操作
          opsForSet --> set 操作
          opsForValue --> string 操作
          opsForZSet --> Zset 操作

          3.3.3 StringRedisTemplate 默認序列化機制

          public class StringRedisTemplate extends RedisTemplate<String, String> {

          /**
          * Constructs a new StringRedisTemplate instance. {@link #setConnectionFactory(RedisConnectionFactory)}
          * and {@link #afterPropertiesSet()} still need to be called.
          */

          public StringRedisTemplate() {
          RedisSerializer stringSerializer = new StringRedisSerializer();
          setKeySerializer(stringSerializer);
          setValueSerializer(stringSerializer);
          setHashKeySerializer(stringSerializer);
          setHashValueSerializer(stringSerializer);
          }
          }

          四、RedissonClient 操作示例

          4.1 基本配置

          4.1.1、Maven pom 引入


          org.springframework.boot
          spring-boot-starter-data-redis


          org.redisson
          redisson
          3.8.2
          true


          org.redisson
          redisson-spring-boot-starter
          LATEST


          4.1.2、添加配置文件 Yaml 或者 json 格式

          redisson-config.yml

          # Redisson 配置
          singleServerConfig:
          address: "redis://192.168.1.140:6379"
          password: null
          clientName: null
          database: 15 #選擇使用哪個數(shù)據(jù)庫0~15
          idleConnectionTimeout: 10000
          pingTimeout: 1000
          connectTimeout: 10000
          timeout: 3000
          retryAttempts: 3
          retryInterval: 1500
          reconnectionTimeout: 3000
          failedAttempts: 3
          subscriptionsPerConnection: 5
          subscriptionConnectionMinimumIdleSize: 1
          subscriptionConnectionPoolSize: 50
          connectionMinimumIdleSize: 32
          connectionPoolSize: 64
          dnsMonitoringInterval: 5000
          #dnsMonitoring: false

          threads: 0
          nettyThreads: 0
          codec:
          class: "org.redisson.codec.JsonJacksonCodec"
          transportMode: "NIO"


          或者,配置 redisson-config.json

          {
          "singleServerConfig": {
          "idleConnectionTimeout": 10000,
          "pingTimeout": 1000,
          "connectTimeout": 10000,
          "timeout": 3000,
          "retryAttempts": 3,
          "retryInterval": 1500,
          "reconnectionTimeout": 3000,
          "failedAttempts": 3,
          "password": null,
          "subscriptionsPerConnection": 5,
          "clientName": null,
          "address": "redis://192.168.1.140:6379",
          "subscriptionConnectionMinimumIdleSize": 1,
          "subscriptionConnectionPoolSize": 50,
          "connectionMinimumIdleSize": 10,
          "connectionPoolSize": 64,
          "database": 0,
          "dnsMonitoring": false,
          "dnsMonitoringInterval": 5000
          },
          "threads": 0,
          "nettyThreads": 0,
          "codec": null,
          "useLinuxNativeEpoll": false
          }


          4.1.3、讀取配置

          新建讀取配置類

          @Configuration
          public class RedissonConfig {

          @Bean
          public RedissonClient redisson() throws IOException {

          // 兩種讀取方式,Config.fromYAML 和 Config.fromJSON
          // Config config = Config.fromJSON(RedissonConfig.class.getClassLoader().getResource("redisson-config.json"));
          Config config = Config.fromYAML(RedissonConfig.class.getClassLoader().getResource("redisson-config.yml"));
          return Redisson.create(config);
          }
          }

          或者,在 application.yml 中配置如下

          spring:
          redis:
          redisson:
          config: classpath:redisson-config.yaml

          4.2 使用示例

          @RestController
          @RequestMapping("/")
          public class TeController {

          @Autowired
          private RedissonClient redissonClient;

          static long i = 20;
          static long sum = 300;

          // ========================== String =======================
          @GetMapping("/set/{key}")
          public String s1(@PathVariable String key) {
          // 設置字符串
          RBucket keyObj = redissonClient.getBucket(key);
          keyObj.set(key + "1-v1");
          return key;
          }

          @GetMapping("/get/{key}")
          public String g1(@PathVariable String key) {
          // 設置字符串
          RBucket keyObj = redissonClient.getBucket(key);
          String s = keyObj.get();
          return s;
          }

          // ========================== hash =======================-=

          @GetMapping("/hset/{key}")
          public String h1(@PathVariable String key) {

          Ur ur = new Ur();
          ur.setId(MathUtil.randomLong(1,20));
          ur.setName(key);
          // 存放 Hash
          RMap ss = redissonClient.getMap("UR");
          ss.put(ur.getId().toString(), ur);
          return ur.toString();
          }

          @GetMapping("/hget/{id}")
          public String h2(@PathVariable String id) {
          // hash 查詢
          RMap ss = redissonClient.getMap("UR");
          Ur ur = ss.get(id);
          return ur.toString();
          }

          // 查詢所有的 keys
          @GetMapping("/all")
          public String all(){
          RKeys keys = redissonClient.getKeys();
          Iterable keys1 = keys.getKeys();
          keys1.forEach(System.out::println);
          return keys.toString();
          }

          // ================== ==============讀寫鎖測試 =============================

          @GetMapping("/rw/set/{key}")
          public void rw_set(){
          // RedissonLock.
          RBucket ls_count = redissonClient.getBucket("LS_COUNT");
          ls_count.set("300",360000000l, TimeUnit.SECONDS);
          }

          // 減法運算
          @GetMapping("/jf")
          public void jf(){

          String key = "S_COUNT";

          // RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
          // atomicLong.set(sum);
          // long l = atomicLong.decrementAndGet();
          // System.out.println(l);

          RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
          if (!atomicLong.isExists()) {
          atomicLong.set(300l);
          }

          while (i == 0) {
          if (atomicLong.get() > 0) {
          long l = atomicLong.getAndDecrement();
          try {
          Thread.sleep(1000l);
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          i --;
          System.out.println(Thread.currentThread().getName() + "->" + i + "->" + l);
          }
          }


          }

          @GetMapping("/rw/get")
          public String rw_get(){

          String key = "S_COUNT";
          Runnable r = new Runnable() {
          @Override
          public void run() {
          RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
          if (!atomicLong.isExists()) {
          atomicLong.set(300l);
          }
          if (atomicLong.get() > 0) {
          long l = atomicLong.getAndDecrement();
          i --;
          System.out.println(Thread.currentThread().getName() + "->" + i + "->" + l);
          }
          }
          };

          while (i != 0) {
          new Thread(r).start();
          // new Thread(r).run();
          // new Thread(r).run();
          // new Thread(r).run();
          // new Thread(r).run();
          }


          RBucket bucket = redissonClient.getBucket(key);
          String s = bucket.get();
          System.out.println("================線程已結(jié)束================================" + s);

          return s;
          }

          }


          4.3 擴展

          4.3.1 豐富的 jar 支持,尤其是對 Netty NIO 框架

          4.3.2 豐富的配置機制選擇,這里是詳細的配置說明

          關于序列化機制中,就有很多


          4.3.3 API 支持(部分展示),具體的 Redis --> RedissonClient ,?可查看這里

          4.3.4 輕便的豐富的鎖機制的實現(xiàn)

          4.3.4.1 Lock
          4.3.4.2 Fair Lock
          4.3.4.3 MultiLock
          4.3.4.4 RedLock
          4.3.4.5 ReadWriteLock
          4.3.4.6 Semaphore
          4.3.4.7 PermitExpirableSemaphore
          4.3.4.8 CountDownLatch

          五、基于注解實現(xiàn)的 Redis 緩存

          5.1 Maven 和 YML 配置

          參考 RedisTemplate 配置

          另外,還需要額外的配置類

          // todo 定義序列化,解決亂碼問題
          @EnableCaching
          @Configuration
          @ConfigurationProperties(prefix = "spring.cache.redis")
          public class RedisCacheConfig {

          private Duration timeToLive = Duration.ZERO;

          public void setTimeToLive(Duration timeToLive) {
          this.timeToLive = timeToLive;
          }

          @Bean
          public CacheManager cacheManager(RedisConnectionFactory factory) {
          RedisSerializer redisSerializer = new StringRedisSerializer();
          Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

          // 解決查詢緩存轉(zhuǎn)換異常的問題
          ObjectMapper om = new ObjectMapper();
          om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
          om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
          jackson2JsonRedisSerializer.setObjectMapper(om);

          // 配置序列化(解決亂碼的問題)
          RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
          .entryTtl(timeToLive)
          .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
          .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
          .disableCachingNullValues();

          RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
          .cacheDefaults(config)
          .build();
          return cacheManager;
          }

          }

          5.2 使用示例

          @Transactional
          @Service
          public class ReImpl implements RedisService {

          @Resource
          private CustomerRepo customerRepo;
          @Resource
          private StringRedisTemplate stringRedisTemplate;

          public static final String REDIS_CUSTOMERS_ONE = "Customers";

          public static final String REDIS_CUSTOMERS_ALL = "allList";

          // =====================================================================使用Spring cahce 注解方式實現(xiàn)緩存
          // ==================================單個操作

          @Override
          @Cacheable(value = "cache:customer", unless = "null == #result",key = "#id")
          public CustomersEntity cacheOne(Integer id) {
          final Optional byId = customerRepo.findById(id);
          return byId.isPresent() ? byId.get() : null;
          }

          @Override
          @Cacheable(value = "cache:customer", unless = "null == #result", key = "#id")
          public CustomersEntity cacheOne2(Integer id) {
          final Optional byId = customerRepo.findById(id);
          return byId.isPresent() ? byId.get() : null;
          }

          // todo 自定義redis緩存的key,
          @Override
          @Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")
          public CustomersEntity cacheOne3(Integer id) {
          final Optional byId = customerRepo.findById(id);
          return byId.isPresent() ? byId.get() : null;
          }

          // todo 這里緩存到redis,還有響應頁面是String(加了很多轉(zhuǎn)義符\,),不是Json格式
          @Override
          @Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")
          public String cacheOne4(Integer id) {
          final Optional byId = customerRepo.findById(id);
          return byId.map(JSONUtil::toJsonStr).orElse(null);
          }

          // todo 緩存json,不亂碼已處理好,調(diào)整序列化和反序列化
          @Override
          @Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")
          public CustomersEntity cacheOne5(Integer id) {
          Optional byId = customerRepo.findById(id);
          return byId.filter(obj -> !StrUtil.isBlankIfStr(obj)).orElse(null);
          }



          // ==================================刪除緩存
          @Override
          @CacheEvict(value = "cache:customer", key = "'cacheOne5' + '.' + #id")
          public Object del(Integer id) {
          // 刪除緩存后的邏輯
          return null;
          }

          @Override
          @CacheEvict(value = "cache:customer",allEntries = true)
          public void del() {

          }

          @CacheEvict(value = "cache:all",allEntries = true)
          public void delall() {

          }
          // ==================List操作

          @Override
          @Cacheable(value = "cache:all")
          public List cacheList() {
          List all = customerRepo.findAll();
          return all;
          }

          // todo 先查詢緩存,再校驗是否一致,然后更新操作,比較實用,要清楚緩存的數(shù)據(jù)格式(明確業(yè)務和緩存模型數(shù)據(jù))
          @Override
          @CachePut(value = "cache:all",unless = "null == #result",key = "#root.methodName")
          public List cacheList2() {
          List all = customerRepo.findAll();
          return all;
          }

          }



          5.3 擴展

          基于 spring 緩存實現(xiàn)

          阿里云服務器白送一年2核2g活動進行中。。。


          如何獲?。?/span>


          掃二維碼,加我微信,備注:阿里云

          ?注意,不要亂回復?

          沒錯,不是機器人
          記得一定要等待,等待才有好東西
          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  三级伦理91 | 日逼黄色| 亚洲成人内射 | 91九色在线 | 国产精品卡一卡二在线 |