`
Everyday都不同
  • 浏览: 722683 次
  • 性别: Icon_minigender_1
  • 来自: 宇宙
社区版块
存档分类
最新评论

redis作为消息队列的使用

阅读更多

========================== 2017/3/31更新=======================

redisson实现了分布式和可扩展的java数据结构,支持的数据结构有:List, Set, Map, Queue, SortedSet, ConcureentMap, Lock, AtomicLong, CountDownLatch。并且是线程安全的,底层使用Netty 4实现网络通信。和jedis相比,功能比较简单,不支持排序,事务,管道,分区等redis特性,可以认为是jedis的补充,不能替换jedis。

redission.getQueue支持队列

==============================================================

 

在redis支持的数据结构中,有一个是集合list. 对List的操作常见的有lpush  lrange等。在这种常见的操作时,我们是把集合当做典型意义上的‘集合’来使用的。往往容易被忽视的是List作为“队列”的使用情况。

反编译redis的jar包,会发现:

 public String rpop(String key)
  {
    checkIsInMulti();
    this.client.rpop(key);
    return this.client.getBulkReply();
  }

public String rpoplpush(String srckey, String dstkey)
  {
    checkIsInMulti();
    this.client.rpoplpush(srckey, dstkey);
    return this.client.getBulkReply();
  }

public String lpop(String key)
  {
    checkIsInMulti();
    this.client.lpop(key);
    return this.client.getBulkReply();
  }

 pop意为“弹”,是队列里的取出元素。rpop意为"right pop"意思就是从队列的右边取元素,lpop就是"left pop"当然就是从队列的左边取元素了。对应取元素,我们往队列里面Push元素同样有2个方向:

public Long lpush(String key, String[] strings)
  {
    checkIsInMulti();
    this.client.lpush(key, strings);
    return this.client.getIntegerReply();
  }

public Long rpush(String key, String[] strings)
  {
    checkIsInMulti();
    this.client.rpush(key, strings);
    return this.client.getIntegerReply();
  }

 好了,下面正式开始测试下redis中List数据结构作为队列的使用方法:

假设我需要往队列里面Push map,该怎么做呢? push  String值的话比价简单,这里不再研究了……

 

往队列里push map的话,有以下2种方式:

第一种:

往队列里push一个map:

class PushThread implements Runnable {
	
	@Override
	public void run() {
		Jedis jedis = null;
		try{
			jedis = JedisPoolUtils.getJedis();
			
			for(int i=0; i<10; i++) {
				Map map = new HashMap();
				map.put("test", "test" + i);
				map.put("ok", "ok" + i);
				jedis.lpush("test".getBytes(), ObjectUtils.objectToBytes(map));//Object对象转换成byte数组的方法,这里省略
			}	
			
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally{
			JedisPoolUtils.returnRes(jedis);
		}
	}
	
}

 从队列里取出map:

class PopThread implements Runnable {

	@Override
	public void run() {
		Jedis jedis = null;
		try{
			jedis = JedisPoolUtils.getJedis();
			
			for(int i=0; i<10; i++) {
				byte[] key = jedis.rpop("test".getBytes());
				System.out.println("弹出:" + ObjectUtils.bytesToObject(key));//byte数组转换为Object对象的方法,这里省略

			}	
			
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally{
			JedisPoolUtils.returnRes(jedis);
		}
	}

 依次启动Push线程和pop线程,可在pop线程端看到打印结果:

弹出:{ok=ok0, test=test0}

弹出:{ok=ok1, test=test1}

弹出:{ok=ok2, test=test2}

弹出:{ok=ok3, test=test3}

弹出:{ok=ok4, test=test4}

弹出:{ok=ok5, test=test5}

弹出:{ok=ok6, test=test6}

弹出:{ok=ok7, test=test7}

弹出:{ok=ok8, test=test8}

弹出:{ok=ok9, test=test9}

 

第二种方式:

因为第一种方式毕竟需要在byte数组和Object对象之间来回转换,效率上可能存在一定影响。所以我们加以改进。不妨只把map的key放在一个队列中,取队列元素时,只取key,然后根据key取map即可。

push:

class PushThread implements Runnable {
	
	@Override
	public void run() {
		Jedis jedis = null;
		try{
			jedis = JedisPoolUtils.getJedis();
			
			for(int i=0; i<10; i++) {
				Map map = new HashMap();
				map.put("test", "test" + i);
				map.put("ok", "ok" + i);
				String key = "map" + i;
				jedis.lpush("test", key);//把所有map的key放入一个队列test中
				jedis.hmset(key, map);
			}	
			
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally{
			JedisPoolUtils.returnRes(jedis);
		}
}

 pop元素:

class PopThread implements Runnable {

	@Override
	public void run() {
		Jedis jedis = null;
		try{
			jedis = JedisPoolUtils.getJedis();
			
			for(int i=0; i<10; i++) {
				String key = jedis.rpop("test");
				System.out.println("弹出:" + jedis.hgetAll(key));
			}	
			
			
		} catch(Exception e) {
			e.printStackTrace();
		} finally{
			JedisPoolUtils.returnRes(jedis);
		}
	}
	
}

  依次启动Push线程和pop线程,可在pop线程端看到打印结果:

弹出:{test=test0, ok=ok0}

弹出:{test=test1, ok=ok1}

弹出:{test=test2, ok=ok2}

弹出:{test=test3, ok=ok3}

弹出:{test=test4, ok=ok4}

弹出:{test=test5, ok=ok5}

弹出:{test=test6, ok=ok6}

弹出:{test=test7, ok=ok7}

弹出:{test=test8, ok=ok8}

弹出:{test=test9, ok=ok9}

 

两种方式效果一样,只不过第二种效率上更好一些。

注:当你依次从队列里取出元素后,队列在redis中就不存在了,所以当你pop完元素,再尝试pop的话,会报异常:

redis.clients.jedis.exceptions.JedisDataException: value sent to redis cannot be null

同时,redis中这个队列也不复存在了!

 

利用redis作为队列的性质我们可以用它来达到类似ZMQ的作用。。

1
4
分享到:
评论

相关推荐

    redis做消息队列

    在本场景中,Redis作为消息队列使用,替代了传统的Kafka队列,以实现顺序消费和防止高并发时的内存溢出问题。 Redis支持多种数据结构,如字符串、哈希、列表、集合和有序集合等,这些数据结构可以巧妙地应用于消息...

    微服务SpringBoot整合Redis基于Redis的Stream消息队列实现异步秒杀下单

    【微服务SpringBoot整合Redis基于Redis的Stream消息队列实现异步秒杀下单】这篇文章主要讲解了如何在微服务架构中使用SpringBoot整合Redis来构建一个基于Redis Stream的消息队列,以此来实现实时、高效的异步秒杀...

    Qt 应用Redis 实现消息队列

    2. **创建消息队列**:在Redis中,可以使用`LPUSH`命令将消息推入列表,作为队列的后端。当消费者处理消息时,使用`RPOP`或`BLPOP`命令取出并删除消息。如果希望避免消息丢失,可以使用`LPOP`配合阻塞操作,当队列为...

    Redis延时消息队列基于swoole实现的多进程消费端

    标题中的“Redis延时消息队列基于swoole实现的多进程消费端”是指使用Redis作为消息队列,结合Swoole的多进程特性来构建一个高效、可扩展的延迟消息处理系统。在这个系统中,Redis作为一个可靠的键值存储,用于暂存...

    Redis 用于消息队列的存储

    博文a 中的老师,提供了Redis 实现消息队列...整体思路在博文a 中老师已经介绍,及依靠 mvc 框架,通过web端用户提交事件,实现消息入列,通过定时器(Timer)实现按照时间间隔的消息出列,Redis 作为存储媒介,存储消

    13-基于Redis的消息队列之发布订阅模式1

    基于Redis的消息队列之发布订阅模式是指使用Redis作为消息队列的中间件,实现消息的发布和订阅。该模式下,消息的生产者将消息发布到Redis中,而消费者则可以从Redis中订阅和消费消息。该模式可以实现消息的异步处理...

    PHP中利用redis实现消息队列处理高并发请求思路详解.rar

    Redis作为一款高性能的键值数据库,常被用于构建消息队列,因为它提供了丰富的数据结构(如列表、集合、通道等)和原子操作,非常适合于实现消息的发布与订阅、入队与出队等操作。 在PHP中,我们可以使用Predis或...

    基于redis实现的消息队列

    标题中的“基于redis实现的消息队列”指的是使用Redis这一开源数据结构存储系统来构建消息队列(Message Queue, MQ)的解决方案。Redis以其高性能、丰富的数据结构和内存存储特性,常被用作构建消息队列的底层技术。...

    redis消息队列

    1. 队列结构:Redis 中的消息队列通常使用 List 或 Stream 数据结构实现。List 可以看作是先进先出(FIFO)的数据结构,而 Stream 提供了更丰富的消息管理功能,包括时间戳和消息ID。 2. 生产者:生产者通过 `LPUSH...

    Thinkphp6 redis队列 消息事件 gatewayworker聊天打通版

    `Redis`作为队列驱动,提供了可靠的消息传输和存储。 整合以上技术,我们可以这样实现聊天系统: 1. 用户通过客户端与`GatewayWorker`建立长连接,`GatewayWorker`记录用户的连接状态。 2. 用户发送消息到服务器,...

    Go-Delayer-基于Redis的延迟消息队列中间件

    Redis作为一个内存数据库,具有高并发、低延迟的特性,非常适合做消息队列的存储。Go-Delayer通过Redis的有序集合(Sorted Set)数据结构来存储延迟消息,其中每个消息都有一个时间戳作为分数,这样可以方便地按时间...

    使用Redis作为消息队列服务场景应用案例

    消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器。在目前广泛的Web应用中,都会出现一种场景:在某一个时刻,网站会迎来一个用户请求的高峰期(比如:淘宝的双十一购物狂欢节,12306的春运抢票...

    spring-redis-mq, 基于 Spring 和 Redis 的分布式消息队列(MessageQueue)实现.zip

    Redis作为消息代理,其丰富的数据结构(如字符串、列表、哈希表等)和丰富的操作命令为实现消息队列提供了便利。例如,我们可以利用Redis的`LPUSH/RPOP`命令来构建一个FIFO(先进先出)的消息队列。消息生产者通过`...

    go实现redis消息队列

    同时,为了保证数据的一致性,可以使用Channel作为队列的同步原语,确保消息被正确且唯一的消费。 2. **Topic与Group注册**:在消息队列设计中,Topic通常用于消息分类,允许生产者将不同类型的事件发送到不同的...

    基于python实现操作redis及消息队列

    本文将详细介绍如何使用Python的redis库来操作Redis以及处理消息队列。 首先,我们需要导入`redis`库,然后创建一个连接池`redisPool`,通过指定Redis服务器的IP地址、端口和数据库编号。例如: ```python import ...

    针对java、mysql、redis、消息队列开发的一款面经、题型的应试网站

    3. **Redis**: Redis作为内存数据库,适用于高速读写场景。面试时会测试对键值对数据结构的理解(如字符串、哈希、列表、集合、有序集合),以及Redis持久化机制(RDB和AOF)、事务、发布订阅、主从复制和哨兵系统等...

    redis面试题之消息队列.zip

    本文将深入探讨Redis作为消息队列的实现及其相关知识点。 1. **Redis消息队列的基础概念** - **发布/订阅(Pub/Sub)模式**:Redis提供了简单的消息发布订阅功能,允许一个或多个客户端订阅特定的频道,当有其他...

    12-基于Redis的消息队列之生产消费者模式1

    Redis作为一个内存数据库,具有快速读写的能力,因此非常适合用作消息队列的底层存储。 在构建基于Redis的消息队列时,我们需要引入一系列的依赖。从提供的`pom.xml`文件中可以看出,项目继承自`common-parent`,并...

    使用redis做任务队列分发子任务

    总结起来,使用Redis作为任务队列分发子任务,能够充分利用其高性能和丰富的特性,提升分布式系统中任务处理的效率和可靠性。在实际项目中,结合业务需求,合理设计任务队列的架构和策略,可以进一步优化系统性能,...

Global site tag (gtag.js) - Google Analytics