redis如何實現消息隊列

1、覆盤面試

遇到面試問到:若是我想在redis實現隊列,會用到哪一個命令?根據redis手冊關於Redis 列表(List) 命令主要操做有四種非阻塞版lpush/lpop/rpush/rpop,兩種阻塞版本blpop/brpop,l和r表明左(left)和右(right)縮寫,push表明添加也叫壓入,pop表明彈出。基本知足先進入先出(FIFO)效果就完成了基本的隊列,本次GitHub實驗代碼倉庫。java

經過命令模擬隊列

RDM Redis Console
鏈接中...
已鏈接。
localhost:0>lpush mylist a b c d
"4"
localhost:0>rpop mylist
"a"
localhost:0>rpop mylist
"b"
localhost:0>rpop mylist
"c"
localhost:0>rpop mylist
"d"
localhost:0>rpop mylist
null
localhost:0>
複製代碼

2、java模擬隊列實現生產者消費者模式

redis配置常量

package io.charles;

public class Constant {
    /** * redis連接地址 */
    public static final String host = "127.0.0.1";
    /** * redis啓動端口 */
    public static final int port = 6379;
    /** * 正式隊列列表名稱 */
    public static final String task_queue = "task-queue";
    /** * 臨時隊列列表名稱 */
    public static final String tmp_queue = "tmp-queue";
}
複製代碼

TaskProducer模擬生產者

package io.charles;

/** * 用於模擬生產者 */

import java.util.Random;
import java.util.UUID;

import redis.clients.jedis.Jedis;

public class TaskProducer implements Runnable {
    Jedis jedis = new Jedis(Constant.host, Constant.port);

    public void run() {
        Random random = new Random();
        while (true) {
            try {
                Thread.sleep(random.nextInt(600) + 600);
                // 模擬生成一個任務
                UUID taskid = UUID.randomUUID();
                //將任務插入任務隊列:task-queue
                jedis.lpush(Constant.task_queue, taskid.toString());
                System.out.println("插入了一個新的任務: " + taskid);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
複製代碼

TaskConsumer模擬消費者

package io.charles;

import java.util.Random;

import redis.clients.jedis.Jedis;

/** * 模擬消費者 */
public class TaskConsumer implements Runnable {
    Jedis jedis = new Jedis(Constant.host, Constant.port);

    public void run() {
        Random random = new Random();

        while (true) {

            //從任務隊列"task-queue"中獲取一個任務,並將該任務放入臨時隊列"tmp-queue"
            String taskid = jedis.rpoplpush(Constant.task_queue, Constant.tmp_queue);

            // 模擬一下:睡覺
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //模擬成功和失敗的偶然現象
            if (random.nextInt(13) % 7 == 0) {// 模擬失敗的狀況,機率爲2/13
                //將本次處理失敗的任務從臨時隊列"tmp-queue"中,彈回任務隊列"task-queue"
                jedis.rpoplpush(Constant.task_queue, Constant.tmp_queue);
                System.out.println(taskid + "處理失敗,被彈回任務隊列");

            } else {// 模擬成功的狀況
                // 將本次任務從臨時隊列"tmp-queue"中清除
                jedis.rpop(Constant.tmp_queue);
                System.out.println(taskid + "處理成功,被清除");
            }
        }
    }
}
複製代碼

TaskShedulerSystem啓動生產者和消費者線程

package io.charles;

public class TaskShedulerSystem {
    public static void main(String[] args) throws Exception {

        // 啓動一個生產者線程,模擬任務的產生
        new Thread(new TaskProducer()).start();

        Thread.sleep(15000);

        //啓動一個線程者線程,模擬任務的處理
        new Thread(new TaskConsumer()).start();
    }
}
複製代碼

3、參考資料

  1. redis中文命令手冊
  2. GitHub實驗代碼倉庫
相關文章
相關標籤/搜索