redis日常梳理

几点理解redis

redis是非关系型数据。
操作redis类似于操作数据库,使用原生的jedis就是每次使用时获取一个连接,然后操作数据,操作完归还或者关闭连接,使用spring框架连接的话可以直接注入xxTemplate对象,使用template的api操作数据库。
redis的基本使用主要是基于redis支持的五种数据类型,根据不同的数据结构特性结合实际业务需求来实现不同的业务场景。
redis高级使用就是分布式事务,分布式锁;目前尚在学习探索…

如何操作redis

主流集成redis的方式:

  1. 集成官方推荐的jedis
  2. 进一步封装jedis的redisson
  3. spring框架自带的redisTemplate
    Jedis和Redisson都是JAVA对redis操作的封装。jedis只是简单的封装了redis的api库,可以看做是jedis的客户端, 它的方法和redis的命令相似。Redisson不仅封装了redis,还封装了对更多数据结构的支持,以及锁等功能,总得来说二者之间Redisson更加丰富更强大,jedis偏原生,更加灵活。

环境搭建

新创建springboot项目

导入start依赖

        <!--redis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

jedis集成

Jedis 是Java 实现的Redis 客户端,偏原生,使用主要是使用jedisPool。

## 配置连接池的参数信息
@Configuration
public class JedisConfig {

    private JedisPoolConfig jedisPoolConfig;

    @Bean
    public JedisPoolConfig generateJedisPool(){
        this.jedisPoolConfig = new JedisPoolConfig();
        //可分配实例数-最大连接数
        jedisPoolConfig.setMaxTotal(8);
        //最大空闲连接数
        jedisPoolConfig.setMaxIdle(8);
        //最大等待时间
        jedisPoolConfig.setMaxWaitMillis(1000);

        return jedisPoolConfig;
    }
}
## 创建redis工具类 操作redis (仅做项目结构展示,util中代码可自行忽略)
@Component
public class JedisUtil {
    private static final Long RELEASE_SUCCESS = 1L;
    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    private long timeout = 100; //获取锁的超时时间
    @Value("${spring.redis.database}")
    private int databaseIndex;
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.commandTimeout}")
    private int redisTimeout;
    
    @Autowired
    private JedisConfig poolConfig;
    private volatile JedisPool jedisPool = null;

    //构建连接池
    //单例 懒汉加载模式
    public JedisPool getInstance() {
        if (jedisPool == null) {
            this.jedisPool = new JedisPool(poolConfig.generateJedisPool(),
                    this.host, this.port, this.redisTimeout, this.password, this.databaseIndex
            );
            return jedisPool;
        }
        return this.jedisPool;
    }
        /**
     * 尝试获取分布式锁
     *
     * @param lockKey    锁
     * @param requestId  请求标识 (可用于避免消息重复消费)
     * @param expireTime 超时时间 (宕机导致无法释放锁)
     * @return
     */
    public boolean tryGetDistributedLock(String lockKey,
                                         String requestId,
                                         int expireTime) {
        JedisPool pool = getInstance();
        Jedis jedis = null;
        long start = System.currentTimeMillis();

        try {
            jedis = pool.getResource();
            while (true) {
                //nx 仅在键不存在时 设置键

                String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST);
                if (LOCK_SUCCESS.equals(result)) {
                    return true;
                } else {
                    //则循环等待 在timeout时间内仍未获取到锁 则获取失败
                    long waitTime = System.currentTimeMillis() - start;
                    if (waitTime >= timeout) {
                        return false;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            //异常 直接关闭连接池
            pool.close();
            e.printStackTrace();
            return false;
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }

    }


    /**
     * 释放分布式锁
     * @param lockKey 锁
     * @param requestId  请求标识
     * @return
     */
    public boolean releaseDistributedLock(String lockKey , String requestId){

        if (StringUtils.isEmpty(lockKey) || StringUtils.isEmpty(requestId)) {
            return true;
        }
        JedisPool pool = getInstance();
        Jedis jedis = null;
        try {
            jedis = pool.getResource();//每次操作时向pool借用个jedis对象,用完即还
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
            if (RELEASE_SUCCESS.equals(result)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
            return false;
        } finally {
            returnResource(pool, jedis);
        }

    }

    private void returnResource(JedisPool pool, Jedis jedis) {
        if (jedis != null) {
            pool.returnResource(jedis);
        }

    }

}

spring的redisTemplate

## 使用方式简单粗暴,直接注入template即可使用Java代码操作数据库,
实际使用再封装一层util方便项目中调用即可
@Component
public class RedisUtil {
	@Resource
	private StringRedisTemplate stringRedisTemplate;

	/**
	 * 存放string类型
	 * 
	 * @param key
	 *            key
	 * @param data
	 *            数据
	 * @param timeout
	 *            超时间
	 */
	public void setString(String key, String data, Long timeout) {
		try {

			stringRedisTemplate.opsForValue().set(key, data);
			if (timeout != null) {
				stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
			}

		} catch (Exception e) {

		}

	}

	/**
	 * 开启Redis 事务
	 *
	 */
	public void begin() {
		// 开启Redis 事务权限
		stringRedisTemplate.setEnableTransactionSupport(true);
		// 开启事务
		stringRedisTemplate.multi();

	}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值