Redis结合springboot配置,redis实现异步(类似消息队列)操作——(学习笔记)

Redis 是一个开源(BSD许可),内存储存的数据结构服务器,可作为数据库,高速缓存,消息队列代理。它支持字符串,哈希表,列表,集合,有序集合,位图,hyperloglogs等数据类型。内置复制,lua脚本,LRU回收,事物以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区

Redis优势

  • 性能极高:Redis的读取速度是11万次每秒,写速度是8.1万次每秒。
  • 丰富的数据类型:Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子性:Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
  • 丰富特性:Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Redis命令(连接本地或远程)

启动 redis 客户端,打开终端并输入命令 redis-cli。该命令会连接本地的 redis 服务。

$redis-cli
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING

在远程服务上执行命令

$redis-cli -h 127.0.0.1 -p 6379 -a "mypass"
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PING

Redis 键(key)

DEL 是一个命令, w3ckey 是一个键。 如果键被删除成功,命令执行后输出 (integer) 1,否则将输出 (integer) 0

redis 127.0.0.1:6379> SET w3ckey redis
OK
redis 127.0.0.1:6379> DEL w3ckey
(integer) 1

Redis 键(key)

序号 命令及描述
1 DEL key 该命令用于在 key 存在是删除 key。
2 DUMP key 序列化给定 key ,并返回被序列化的值。
3 EXISTS key 检查给定 key 是否存在。
4 EXPIRE key seconds 为给定 key 设置过期时间。
5 EXPIREAT key timestamp EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
6 PEXPIRE key milliseconds 设置 key 的过期时间亿以毫秒计。
7 PEXPIREAT key milliseconds-timestamp 设置 key 过期时间的时间戳(unix timestamp) 以毫秒计
8 KEYS pattern 查找所有符合给定模式( pattern)的 key 。
9 MOVE key db 将当前数据库的 key 移动到给定的数据库 db 当中。
10 PERSIST key 移除 key 的过期时间,key 将持久保持。
11 PTTL key 以毫秒为单位返回 key 的剩余的过期时间。
12 TTL key 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
13 RANDOMKEY 从当前数据库中随机返回一个 key 。
14 RENAME key newkey 修改 key 的名称
15 RENAMENX key newkey 仅当 newkey 不存在时,将 key 改名为 newkey 。
16 TYPE key 返回 key 所储存的值的类型。

其余部分:官网地址 http://www.redis.net.cn/tutorial/3509.html

springboot使用redis

  1. Maven依赖
       
        
            org.springframework.boot
            spring-boot-starter-data-redis
            
                
                    redis.clients
                    jedis
                
                
                    io.lettuce
                    lettuce-core
                
            
        
        
        
            redis.clients
            jedis
            2.9.0
        

2.配置文件 .yml

  ## redis相关配置
  redis:
    database: 0
    host: 127.0.0.1
    password: jijl
    port: 6380
    timeout: 6000ms  # 连接超时时长(毫秒)
    jedis:
      pool:
        max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 10      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

3.redis的配置文件在后面的代码中,写一个redis的工具类 这里摘用项目中的代码
通过源码可以知道,SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate。
这个RedisService 交给Spring容器实例化,使用时直接注解注入。

 package com.laiganhlj.dlc.common.redis;


import com.laiganhlj.dlc.common.result.SysConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author: jijl
 * @Description: redis工具类
 * @Date: 2018/7/2 16:53
 **/
@Slf4j
@Component
public class RedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    public void redisColse() {
        RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
    }
    //=============================common============================

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        long timeOut = redisTemplate.getExpire(key, TimeUnit.SECONDS);
        redisColse();
        return timeOut;
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        boolean flag = false;
        try {
            flag = redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
        redisColse();
    }

    //============================String=============================

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        Object o = redisTemplate.opsForValue().get(key);
        redisColse();
        return o;
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        boolean flag = false;
        try {
            redisTemplate.opsForValue().set(key, value);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key, Object value, long time) {
        boolean flag = false;
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        long timeOut = redisTemplate.opsForValue().increment(key, delta);
        redisColse();
        return timeOut;
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        long timeOut = redisTemplate.opsForValue().increment(key, -delta);
        return timeOut;
    }

    //================================Map=================================

    /**
     * HashGet
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public Object hget(String key, String item) {
        Object o = redisTemplate.opsForHash().get(key, item);
        redisColse();
        return o;
    }

    /**
     * 获取hashKey对应的所有键值
     *
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        Map<Object, Object> map = redisTemplate.opsForHash().entries(key);
        redisColse();
        return map;
    }

    /**
     * HashSet
     *
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map<String, Object> map) {
        boolean flag = false;
        try {
            redisTemplate.opsForHash().putAll(key, map);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * HashSet 并设置时间
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        boolean flag = false;
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        boolean flag = false;
        try {
            redisTemplate.opsForHash().put(key, item, value);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        boolean flag = false;
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
        redisColse();
    }

    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        boolean flag = redisTemplate.opsForHash().hasKey(key, item);
        redisColse();
        return flag;
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item, double by) {
        double num = redisTemplate.opsForHash().increment(key, item, by);
        redisColse();
        return num;
    }

    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item, double by) {
        double num = redisTemplate.opsForHash().increment(key, item, -by);
        redisColse();
        return num;
    }

    //============================set=============================

    /**
     * 根据key获取Set中的所有值
     *
     * @param key 键
     * @return
     */
    public Set<Object> sGet(String key) {
        try {
            Set<Object> set = redisTemplate.opsForSet().members(key);
            return set;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            redisColse();
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        boolean flag = false;
        try {
            flag = redisTemplate.opsForSet().isMember(key, value);
            return flag;
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        } finally {
            redisColse();
            return flag;
        }
    }

    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            long num = redisTemplate.opsForSet().add(key, values);
            return num;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            redisColse();
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0) expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            redisColse();
        }
    }

    /**
     * 获取set缓存的长度
     *
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            long num = redisTemplate.opsForSet().size(key);
            return num;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            redisColse();
        }
    }

    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            redisColse();
        }
    }
    //===============================list=================================

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束  0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            List<Object> list = redisTemplate.opsForList().range(key, start, end);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            redisColse();
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     * @return
     */
    public long lGetListSize(String key) {
        try {
            long num = redisTemplate.opsForList().size(key);
            return num;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            redisColse();
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            Object o = redisTemplate.opsForList().index(key, index);
            return o;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            redisColse();
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            redisColse();
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            redisColse();
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            redisColse();
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            redisColse();
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            redisColse();
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        } finally {
            redisColse();
        }
    }

    //===============================业务部分=================================

    /**
     * 发送消息
     *
     * @param channel 通道
     * @param message 消息
     */
    public void sendMessage(String channel, Serializable message) {
        redisTemplate.convertAndSend(channel, message);
    }

    /**
     * 获取授权主体
     *
     * @param uniqueId 唯一编号
     * @return
     */
    public Object getAuthorizedSubject(String uniqueId) {
        return get(SysConstant.PROJECT_NAME + uniqueId);
    }

    /**
     * 删除授权主体
     *
     * @param uniqueId 唯一编号
     */
    public void delAuthorizedSubject(String uniqueId) {
        del(SysConstant.PROJECT_NAME + uniqueId);
    }

    /**
     * 设置授权主体
     *
     * @param uniqueId 唯一编号
     * @param obj      主体
     * @param time     过期时间
     * @return
     */
    public boolean setAuthorizedSubject(String uniqueId, Object obj, long time) {
        return set(SysConstant.PROJECT_NAME + uniqueId, obj, time);
    }
}

redis的异步(类似消息队列)使用

  1. 创建接受消息类 注入ReceiveMessage ,创建redis工具类 上面有
package com.laiganhlj.dlc.common.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.concurrent.CountDownLatch;

/**
 * 接收消息
 */
@Slf4j
public class ReceiveMessage {

    private CountDownLatch latch;

    @Autowired
    public ReceiveMessage(CountDownLatch countDownLatch) {
        this.latch = countDownLatch;
    }
 

    public void receiveMessage(Serializable message) {
        log.info("message接收到消息了:{}", message);
   
    }

    public void receiveMessage2(Serializable message) {
        log.info("message2接收到消息了:{}", message);
    }

}


  1. redis配置类
package com.laiganhlj.dlc.config;


import com.laiganhlj.dlc.common.redis.ReceiveMessage;
import com.laiganhlj.dlc.common.result.SysConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.Serializable;
import java.util.concurrent.CountDownLatch;

/**
 * @Author: jijl
 * @Description: redis配置类
 * @Date: 2018/6/27 15:05
 **/
@Slf4j
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<Serializable, Serializable> redisTemplate(
            JedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Serializable, Serializable> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.afterPropertiesSet();
        redisTemplate.opsForValue().get(SysConstant.PROJECT_NAME);
        log.info("-------------------------------------------------");
        log.info("---------------local redis success---------------");
        log.info("-------------------------------------------------");
        return redisTemplate;
    }

    /**
     * 配置监听器1
     *
     * @return
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(ReceiveMessage receiveMessage) {
        MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(receiveMessage, "receiveMessage");
        messageListenerAdapter.setSerializer(new JdkSerializationRedisSerializer());
        return messageListenerAdapter;
    }


    /**
     * 配置监听器2
     *
     * @return
     */
    @Bean
    public MessageListenerAdapter listenerAdapter2(ReceiveMessage receiveMessage) {
        MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(receiveMessage, "receiveMessage2");
        messageListenerAdapter.setSerializer(new JdkSerializationRedisSerializer());
        return messageListenerAdapter;
    }

    /**
     * 初始化监听器
     *
     * @param connectionFactory
     * @param listenerAdapter
     * @param listenerAdapter2
     * @return
     */
    @Bean
    public RedisMessageListenerContainer container(JedisConnectionFactory connectionFactory,
                                                   MessageListenerAdapter listenerAdapter,
                                                   MessageListenerAdapter listenerAdapter2) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic(SysConstant.Redis.END_ORDER_MESSAGE_CHANNLE));
        container.addMessageListener(listenerAdapter2, new PatternTopic(SysConstant.Redis.CHANNLE_TWO));
        return container;
    }

    /**
     * 消息监听者1
     *
     * @return
     */
    @Bean
    public ReceiveMessage receiveMessage(CountDownLatch countDownLatch) {
        return new ReceiveMessage(countDownLatch);
    }

    /**
     * 消息监听者2
     *
     * @return
     */
    @Bean
    public ReceiveMessage receiveMessage2(CountDownLatch countDownLatch) {
        return new ReceiveMessage(countDownLatch);
    }

    @Bean
    public CountDownLatch countDownLatch() {
        return new CountDownLatch(1);
    }


}

  1. redis队列使用
    这里使用时把传过来的值进行了序列化操作,接收时进行了反序列化,在对外开放的时候建议使用json
    这里不贴完整代码了
	//注入redis
	@Autowired
	private RedisService redisService;

		//直接调用即可 不会影响主业务逻辑,ReceiveMessage 中接收到可以进行异步操作,平时项目中把发送短信和微信模板消息用redis异步来执行
     redisService.sendMessage("message2", "需要传过去的消息");

你可能感兴趣的:(笔记)