SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)

沙海 2021年8月25日05:33:14Java评论42字数 13893阅读46分18秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/42212.html

使用阻塞的I/O,方法调用同步,程序流需要等到socket处理完I/O才能执行,不支持异步操作。Jedis客户端实例不是线程安全的,需要通过连接池来使用Jedis。用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作。文章源自JAVA秀-https://www.javaxiu.com/42212.html

原文约 2555 | 图片 9 | 建议阅读 6 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)

小哈学Java 文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)文章源自JAVA秀-https://www.javaxiu.com/42212.html

来源:blog.csdn.net/qq_42105629/article/details/102589319文章源自JAVA秀-https://www.javaxiu.com/42212.html

一、Jedis,Redisson,Lettuce三者的区别

共同点:都提供了基于Redis操作的Java API,只是封装程度,具体实现稍有不同。文章源自JAVA秀-https://www.javaxiu.com/42212.html

不同点:文章源自JAVA秀-https://www.javaxiu.com/42212.html

1.1、Jedis

是Redis的Java实现的客户端。支持基本的数据类型如:String、Hash、List、Set、Sorted Set。文章源自JAVA秀-https://www.javaxiu.com/42212.html

特点:使用阻塞的I/O,方法调用同步,程序流需要等到socket处理完I/O才能执行,不支持异步操作。Jedis客户端实例不是线程安全的,需要通过连接池来使用Jedis。文章源自JAVA秀-https://www.javaxiu.com/42212.html

1.2、Redisson

优点点:分布式锁,分布式集合,可通过Redis支持延迟队列。文章源自JAVA秀-https://www.javaxiu.com/42212.html

1.3、 Lettuce

用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。文章源自JAVA秀-https://www.javaxiu.com/42212.html

基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作。文章源自JAVA秀-https://www.javaxiu.com/42212.html

二、RedisTemplate

2.1、使用配置

maven配置引入,(要加上版本号,我这里是因为Parent已声明)文章源自JAVA秀-https://www.javaxiu.com/42212.html

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

application-dev.yml文章源自JAVA秀-https://www.javaxiu.com/42212.html

spring:  redis:    host: 192.168.1.140    port: 6379    password:    database: 15 # 指定redis的分库(共16个0到15)

2.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<CustomersEntity> 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;    }

2.3、扩展

2.3.1、spring-boot-starter-data-redis的依赖包

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)文章源自JAVA秀-https://www.javaxiu.com/42212.html

图片文章源自JAVA秀-https://www.javaxiu.com/42212.html

3.3.2、stringRedisTemplate API(部分展示)
  • opsForHash --> hash操作文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • opsForList --> list操作文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • opsForSet --> set操作文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • opsForValue --> string操作文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • opsForZSet --> Zset操作文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)文章源自JAVA秀-https://www.javaxiu.com/42212.html

图片文章源自JAVA秀-https://www.javaxiu.com/42212.html

3.3.3 StringRedisTemplate默认序列化机制
public class StringRedisTemplate extends RedisTemplate<String, String> { /**  * Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}  * and {@link #afterPropertiesSet()} still need to be called.  */ public StringRedisTemplate() {  RedisSerializer<String> stringSerializer = new StringRedisSerializer();  setKeySerializer(stringSerializer);  setValueSerializer(stringSerializer);  setHashKeySerializer(stringSerializer);  setHashValueSerializer(stringSerializer); } }

三、RedissonClient 操作示例

3.1 基本配置

3.1.1、Maven pom 引入
<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency>    <groupId>org.redisson</groupId>    <artifactId>redisson</artifactId>    <version>3.8.2</version>    <optional>true</optional></dependency><dependency>    <groupId>org.redisson</groupId>    <artifactId>redisson-spring-boot-starter</artifactId>    <version>LATEST</version></dependency>
3.1.2、添加配置文件Yaml或者json格式

redisson-config.yml文章源自JAVA秀-https://www.javaxiu.com/42212.html

# Redisson 配置singleServerConfig:  address: "redis://192.168.1.140:6379"  password: null  clientName: null  database: 15 #选择使用哪个数据库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: falsethreads: 0nettyThreads: 0codec:  class: "org.redisson.codec.JsonJacksonCodec"transportMode: "NIO"

或者,配置 redisson-config.json文章源自JAVA秀-https://www.javaxiu.com/42212.html

{  "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}
3.1.3、读取配置

新建读取配置类文章源自JAVA秀-https://www.javaxiu.com/42212.html

@Configurationpublic 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中配置如下文章源自JAVA秀-https://www.javaxiu.com/42212.html

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

3.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<String> keyObj = redissonClient.getBucket(key);        keyObj.set(key + "1-v1");        return key;    }    @GetMapping("/get/{key}")    public String g1(@PathVariable String key) {        // 设置字符串        RBucket<String> 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<String, Ur> ss = redissonClient.getMap("UR");        ss.put(ur.getId().toString(), ur);        return ur.toString();    }    @GetMapping("/hget/{id}")    public String h2(@PathVariable String id) {        // hash 查询        RMap<String, Ur> ss = redissonClient.getMap("UR");        Ur ur = ss.get(id);        return ur.toString();    }    // 查询所有的 keys    @GetMapping("/all")    public String all(){        RKeys keys = redissonClient.getKeys();        Iterable<String> keys1 = keys.getKeys();        keys1.forEach(System.out::println);        return keys.toString();    }    // ================== ==============读写锁测试 =============================    @GetMapping("/rw/set/{key}")    public void rw_set(){//        RedissonLock.        RBucket<String> 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<String> bucket = redissonClient.getBucket(key);        String s = bucket.get();        System.out.println("================线程已结束================================" + s);        return s;    }}

4.3 扩展

4.3.1 丰富的jar支持,尤其是对 Netty NIO框架文章源自JAVA秀-https://www.javaxiu.com/42212.html

4.3.2 丰富的配置机制选择,这里是详细的配置说明文章源自JAVA秀-https://www.javaxiu.com/42212.html

https://github.com/redisson/redisson/wiki/2.-Configuration文章源自JAVA秀-https://www.javaxiu.com/42212.html

关于序列化机制中,就有很多文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Reis的各种实现(以及Jedis、Redisson、Lettuce的区别比SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)图片

文章源自JAVA秀-https://www.javaxiu.com/42212.html

4.3.3 API支持(部分展示),具体的 Redis --> RedissonClient ,可查看这里文章源自JAVA秀-https://www.javaxiu.com/42212.html

https://github.com/redisson/redisson/wiki/11.-Redis-commands-mapping文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)文章源自JAVA秀-https://www.javaxiu.com/42212.html

图片文章源自JAVA秀-https://www.javaxiu.com/42212.html

4.3.4 轻便的丰富的锁机制的实现文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • Lock文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • Fair Lock文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • MultiLock文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • RedLock文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • ReadWriteLock文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • Semaphore文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • PermitExpirableSemaphore文章源自JAVA秀-https://www.javaxiu.com/42212.html

  • CountDownLatch文章源自JAVA秀-https://www.javaxiu.com/42212.html

四、基于注解实现的Redis缓存

4.1 Maven 和 YML配置

参考 RedisTemplate 配置。文章源自JAVA秀-https://www.javaxiu.com/42212.html

另外,还需要额外的配置类文章源自JAVA秀-https://www.javaxiu.com/42212.html

// 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<String> redisSerializer = new StringRedisSerializer();        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);        // 解决查询缓存转换异常的问题        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;    }}

4.2 使用示例

@Transactional@Servicepublic 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 注解方式实现缓存    // ==================================单个操作    @Override    @Cacheable(value = "cache:customer", unless = "null == #result",key = "#id")    public CustomersEntity cacheOne(Integer id) {        final Optional<CustomersEntity> 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<CustomersEntity> 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<CustomersEntity> byId = customerRepo.findById(id);        return byId.isPresent() ? byId.get() : null;    }    // todo 这里缓存到redis,还有响应页面是String(加了很多转义符\,),不是Json格式    @Override    @Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")    public String cacheOne4(Integer id) {        final Optional<CustomersEntity> byId = customerRepo.findById(id);        return byId.map(JSONUtil::toJsonStr).orElse(null);    }     // todo 缓存json,不乱码已处理好,调整序列化和反序列化    @Override    @Cacheable(value = "cache:customer", unless = "null == #result", key = "#root.methodName + '.' + #id")    public CustomersEntity cacheOne5(Integer id) {        Optional<CustomersEntity> 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<CustomersEntity> cacheList() {        List<CustomersEntity> all = customerRepo.findAll();        return all;    }    // todo 先查询缓存,再校验是否一致,然后更新操作,比较实用,要清楚缓存的数据格式(明确业务和缓存模型数据)    @Override    @CachePut(value = "cache:all",unless = "null == #result",key = "#root.methodName")    public List<CustomersEntity> cacheList2() {        List<CustomersEntity> all = customerRepo.findAll();        return all;    }}

4.3 扩展

基于spring缓存实现文章源自JAVA秀-https://www.javaxiu.com/42212.html

SpringBoot 操作 Redis的各种实现(以及Jedis、Redisson、Lettuce的区别比较)文章源自JAVA秀-https://www.javaxiu.com/42212.html

图片文章源自JAVA秀-https://www.javaxiu.com/42212.html

欢迎一键三连文章源自JAVA秀-https://www.javaxiu.com/42212.html

1. 你真的会写for循环吗?来看看这些常见的for循环优化方式2. SpringCloud常见面试题(2021最新版)3. 神奇的 SQL 之别样的写法 → 行行比较4. 华为OD(外包)社招技术二面,总结复盘最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。文章源自JAVA秀-https://www.javaxiu.com/42212.html

谢谢支持哟 (*^__^*)文章源自JAVA秀-https://www.javaxiu.com/42212.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定