栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot集成Redis缓存及分布式锁示例

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot集成Redis缓存及分布式锁示例

1、pom依赖

            
            org.springframework.boot
            spring-boot-starter-data-redis
        
        
            org.redisson
            redisson-spring-boot-starter
            3.10.2
        
        
            org.redisson
            redisson-spring-data-20
            3.10.2
        
        
2、yml配置
spring:
  cache:
    type: redis
  redis:
    # redis库
    database: 0
#    #方式一: 集群
#    cluster:
#      nodes: 192.168.56.99:6379,192.168.59.100:6379
    #方式二: 单机  二选一
    port: 6379
    host: 127.0.0.1
    # redis 密码
    password:
    # 连接超时时间(毫秒)
    timeout: 1000
    jedis:
      pool:
        # 连接池最大链接数(负数表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(负数表示没有限制)
        max-wait: 3000
        # 连接池最大空闲连接数
        max-idle: 8
        # 连接池最小空闲连接数
        min-idle: 0
3、config配置
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import java.time.Duration;

@Configuration
@EnableCaching
@Slf4j
@AllArgsConstructor
public class RedisConfig extends CachingConfigurerSupport {

    @Resource
    private final RedisProperties redisProperties;

    
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
//      redisCacheManager构造器需要提供一个redisCacheWriter和一个redisCacheConfigurer
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
//      配置cache 序列化为jsonSerializer
        RedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
        RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration
                .defaultCacheConfig()
                .prefixCacheNameWith("cache:")
                .serializeValuesWith(pair)
                .entryTtl(Duration.ofDays(1));//      设置默认过期时间一天
//                .computePrefixWith(cacheName -> "caching:" + cacheName);

//        也可以通过builder来构建
//        RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(defaultCacheConfig).transactionAware().build();
        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);

    }

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();

        //单机
        config.useSingleServer()
                .setAddress("redis://" + redisProperties.getHost()+":"+redisProperties.getPort())
        ;

//        //集群
//        //redis服务器地址,多个逗号分隔
//        RedisProperties.Cluster cluster = redisProperties.getCluster();
//        List nodes = cluster.getNodes();
//        Set nodeSet = new HashSet<>();
//        for (String node : nodes) {
//            nodeSet.add("redis://" + node);
//        }
//        config.useClusterServers()
//                .setScanInterval(2000)
//                .addNodeAddress(nodeSet.toArray(new String[nodeSet.size()]))
//                ;
        return Redisson.create(config);
    }

    
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        RedisTemplate redisTemplate = new RedisTemplate<>();
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);
        // value序列化方式采用jackson
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8);
        //hash的value序列化方式采用jackson
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }

    
    @Bean
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(":");
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(":" + String.valueOf(obj));
            }
            String rsToUse = String.valueOf(sb);
            log.info("自动生成Redis Key -> [{}]", rsToUse);
            return rsToUse;
        };
    }

    
    @Bean
    public CacheErrorHandler errorHandler() {
        log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
        CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
                log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
            }

            @Override
            public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
                log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
            }

            @Override
            public void handleCacheEvictError(RuntimeException e, Cache cache, Object key)    {
                log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
            }

            @Override
            public void handleCacheClearError(RuntimeException e, Cache cache) {
                log.error("Redis occur handleCacheClearError:", e);
            }
        };
        return cacheErrorHandler;
    }
}
 
4、redis锁工具类 
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;


@Component
public class RedissonUtil {
    private static final Logger logger = LoggerFactory.getLogger(RedissonUtil.class);
    
    public static final String SYS_LOCK_FLAG = "lock";

    
    public static final String KEY_SPLIT = ":";
    // 静态属性注入
    private static RedissonClient redissonClient;
    @Autowired
    public void setRedisson(RedissonClient redissonClient) {
        RedissonUtil.redissonClient = redissonClient;
    }


    
    public static boolean getLock(String lockName, long expiresTime,long waitTime) {
        //最长等待时间
        String key = getLockKey(lockName);
        //获取锁对象
        RLock lock = redissonClient.getLock(key);
        //设置锁过期时间,防止死锁的产生
        boolean flag = true;
        try {
            flag = lock.tryLock(waitTime,expiresTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("获取锁成功,Redis Lock key: {}", key);
        return flag;
    }

    
    public static void unlock(String lockName) {
        String key = getLockKey(lockName);
        //获取所对象
        RLock lock = redissonClient.getLock(key);
        // 释放锁,判断要解锁的key是否已被锁定并且是否被当前线程保持
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
            logger.info("释放Redis锁成功,key:{}", key);
        }
    }

    
    private static String getLockKey(String key) {
        return RedissonUtil.SYS_LOCK_FLAG + RedissonUtil.KEY_SPLIT + key;
    }

}
5、缓存及锁示例
@Service
public class UserDemoService {

    
    @Cacheable(cacheNames = "users",key = "#userName")
    public UserDemo getByUserName(String userName){
        UserDemo userDemo = new UserDemo();
        userDemo.setUserName("zhangsan");
        userDemo.setPwd("123456");
        System.out.println("getByUserName:"+userDemo.toString());
        return userDemo;
    }

    
    @CachePut(cacheNames = "users",key = "#userName")
    public UserDemo updateUser(String userName, String pwd){
        UserDemo userDemo = new UserDemo();
        userDemo.setUserName(userName);
        userDemo.setPwd(pwd);
        System.out.println("updateUser:"+userDemo.toString());
        return userDemo;
    }

    
    @CacheEvict(cacheNames = "users",key = "#userName")
    public void delUser(String userName) {
        System.out.println("delUser:"+userName);
    }

    
    @Cacheable(cacheNames = "users", key = "'allUsers'", unless = "#result==null")
    public List allUsers() {
        System.out.println("allUsers:");
        List list = new ArrayList<>();
        return list;
    }

    
    public void test(){
        System.out.println("========开始=====");
        if(RedissonUtil.getLock("mylock",5L,3L)){
            try {
                Thread.sleep(1000*5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            RedissonUtil.unlock("mylock");
            System.out.println("解锁:"+System.currentTimeMillis());
        }else {
            System.out.println("未获得锁:"+System.currentTimeMillis());
        }

    }


}

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号