List(列表)
从头部(左边)插入数据:lpush key v1 v2 v3 从尾部(右边)插入数据:rpush key v1 v2 v3 读取list中指定范围的values:lrange key start end redis> lrange task-queue 0 -1 (-1表示读取整个list) 从头部弹出一个元素:lpop key 从尾部弹出一个元素:rpop key 从一个list的尾部弹出一个元素插入到另一个list:rpoplpush key1 key2 应用案例:任务调度系统 - 生产者不断产生任务,放入task-queue排队。 - 消费者不断拿出任务来处理,同时放入一个tmp-queue暂存, 如果任务处理成功,则清除tmp-queue; 如果任务处理失败,将任务弹回task-queue。
代码实现: A、生产者——模拟产生任务 public class TaskProducer { // 获取一个redis的客户端连接对象(这里我们用的是jedis) public static Jedis getRedisConnection(String host, int port) { Jedis jedis = new Jedis(host, port); return jedis; } public static void main(String[] args) { // redis服务器的ip地址和默认端口 Jedis jedis = getRedisConnection("192.168.2.70", 6379); // 随机数,这里用于间隔生产者任务的产生 Random random = new Random(); // 生成任务 while (true) { // 生成任务的速度有一定的随机性,在1-2秒之间 Thread.sleep(random.nextInt(1000) + 1000); // 生成一个任务 String taskid = UUID.randomUUID().toString(); // 往任务队列"task-queue"中插入,第一次插入时,"task-queue"还不存在 //但是lpush方法会在redis库中创建一条新的list数据 jedis.lpush("task-queue", taskid); System.out.println("向任务队列中插入了一个新的任务: " + taskid); } } } B、消费者——模拟处理任务,并且管理暂存队列 public class TaskConsumer { public static void main(String[] args) { Jedis jedis = new Jedis("192.168.2.70", 6379); Random random = new Random(); while (true) { // 从task-queue中取一个任务,同时放入"tmp-queue" String taskid = jedis.rpoplpush("task-queue", "tmp-queue"); // 模拟处理任务 Thread.sleep(1000); // 模拟有成功又有失败的情况 int nextInt = random.nextInt(13); if(nextInt % 7 == 0){ // 模拟失败的情况 // 失败的情况下,需要将任务从"tmp-queue"弹回"task-queue" jedis.rpoplpush("tmp-queue", "task-queue"); System.out.println("-------任务处理失败: " + taskid); }else{ // 模拟成功的情况 // 成功的情况下,将任务从"tmp-queue"清除 jedis.rpop("tmp-queue"); System.out.println("任务处理成功: " + taskid); } } } } 上述机制是一个简化版,真实版的任务调度系统会更加复杂,如下所示: (增加了一个专门用来管理暂存队列的角色,以便就算消费者程序失败退出,那些处理失败的任务依然可以被弹回task-queue)