Redis – List队列 – 排队业务解决方案

2023-06-07 16:48:32 浏览数 (1)

Redis命令:LPUSH、RPUSH、LRANGE、LPOP、RPOP等

看下工具类 RedisQueueUtil

代码语言:javascript复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;


/**
 * 这里我要说明一下:如果队列长度=0,则Redis将无法查询到此Key
 */
@Component
public class RedisQueueUtil {

    private static RedisTemplate redisTemplate;

    @Autowired
    private void initRedisTemplate(@Qualifier("redisTemplate") RedisTemplate template) {
        redisTemplate = template;
    }

    /**
     * 左插入
     *
     * @param key   Key
     * @param value Value
     * @return 插入后列表的总长度
     */
    public static Long leftPush(String key, String value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 右插入
     *
     * @param key   Key
     * @param value Value
     * @return 插入后列表的总长度
     */
    public static Long rightPush(String key, String value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 取号 (插入是从左边插入,那么取号就是从右边取出)
     * pop:从顶部取出
     *
     * @param key
     * @return
     */
    public static Object takeNumber(String key) {
        Object o = redisTemplate.opsForList().rightPop(key);
        return o;
    }

    /**
     * 查询指定位置的号码,第一位是0。注意这里需要考虑加入分布式锁哦,两步Redis操作!
     * index:指定位置取出
     *
     * @param key
     * @param positon
     * @return
     */
    public static Object takeNumber(String key, Long positon) {
        String element = (String) redisTemplate.opsForList().index(key, positon);
        redisTemplate.opsForList().remove(key, 0, element);
        return element;
    }

    /**
     * 插入到指定元素右边
     * 如果 key 不存在,会创建一个新的列表。如果 pivot 不存在于列表中,则不会插入新元素。如果 pivot 存在于列表中,则将新元素插入到 pivot 右侧。
     *
     * @param key   Key
     * @param pivot 指定元素
     * @param value 要插入到指定元素右边的元素
     * @return
     */
    public static Long rigthPushWithPivot(String key, String pivot, String value) {
        return redisTemplate.opsForList().rightPush(key, pivot, value);
    }

    /**
     * 插入到指定元素左边
     * 例如,假设列表中包含以下元素:[1, 2, 3, 4]
     * 我们执行 leftPush("myList", 2, 5),则列表会变成 [1, 5, 2, 3, 4]。
     * 如果我们执行 leftPush("myList", 6, 5),则列表不会发生变化,因为列表中不存在值为 6 的元素。
     *
     * @param key   Key
     * @param pivot 指定元素
     * @param value 插入到指定元素左边的元素
     * @return
     */
    public static Long leftPushWithPivot(String key, String pivot, String value) {
        return redisTemplate.opsForList().leftPush(key, pivot, value);
    }

    /**
     * 获取队列的长度
     *
     * @param key Key
     * @return 如果是0,则代表Key不存在哦
     */
    public static Long queueSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 获取指定范围的元素
     *
     * @param key   Key
     * @param start 起始位置,第一位是0
     * @param end   终点位置
     * @return
     */
    public static List<String> range(String key, Long start, Long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }
}

调用示例

代码语言:javascript复制
import com.zanglikun.springdataredisdemo.util.RedisQueueUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/redis")
public class RedisQueueController {

    private static String key = "RedisQueue";

    private static int count = 1; // 此字段仅用于在redis看到不动Value无实际作用

    // 正常顺序插入队列
    @GetMapping("/leftPush")
    public String leftPush() {
        Long aLong = RedisQueueUtil.leftPush(key, String.valueOf(count  ));
        return "已经插入到第"   aLong   "位";
    }

    // 倒序插入队列
    @GetMapping("/rightPush")
    public String rightPush() {
        Long aLong = RedisQueueUtil.rightPush(key, String.valueOf(count  ));
        return "已经插入到第"   aLong   "位";
    }

    // 正常取号
    @GetMapping("/rightPop")
    public Object rightPop() {
        Object o = RedisQueueUtil.takeNumber(key);
        return o;
    }

    // 查询指定位置的号码,并未剔除队列。注意position不得是空,如果Key不存在查询结果是空
    @GetMapping("/index")
    public Object index(Long position) {
        if (position == null){
            // 如果position是空,则会抛出异常
            position = 0L;
        }
        Object o = RedisQueueUtil.takeNumber(key,position);
        return o;
    }

    // 队列长度
    @GetMapping("/ququeSize")
    public Long ququeSize() {
        return RedisQueueUtil.queueSize(key);
    }

    // 测试Redis插入到指定Key左边的时候,是第几个Key左边。结果:从左边数第一个
    @GetMapping("/leftPushWithPivot")
    public void leftPushWithPivot(){
        String thisKey = "TEST-Redis-List-Left";
        RedisQueueUtil.leftPush(thisKey,"张三");
        RedisQueueUtil.leftPush(thisKey,"张三");
        RedisQueueUtil.leftPushWithPivot(thisKey,"张三","李四");
        List<String> range = RedisQueueUtil.range(thisKey, 0L, 100L);
        range.forEach(System.out::print); // 李四 张三 张三
    }

    // 测试Redis插入到指定Key左边的时候,是第几个Key左边。结果:从左边数第一个
    @GetMapping("/rigthPushWithPivot")
    public void rigthPushWithPivot(){
        String thisKey = "TEST-Redis-List-Right";
        RedisQueueUtil.leftPush(thisKey,"张三");
        RedisQueueUtil.leftPush(thisKey,"张三");
        RedisQueueUtil.rigthPushWithPivot(thisKey,"张三","李四");
        List<String> range = RedisQueueUtil.range(thisKey, 0L, 100L);
        range.forEach(System.out::print); // 张三 李四 张三
    }
}

0 人点赞