redis的应用场景实在太多了,现在介绍一下它的几大特性之一   发布订阅(pub/sub)。

特性介绍:

  什么是redis的发布订阅(pub/sub)?   Pub/Sub功能(means Publish, Subscribe)即发布及订阅功能。基于事件的系统中,Pub/Sub是目前广泛使用的通信模型,它采用事件作为基本的通信机制,提供大规模系统所要求的松散耦合的交互模式:订阅者(如客户端)以事件订阅的方式表达出它有兴趣接收的一个事件或一类事件;发布者(如服务器)可将订阅者感兴趣的事件随时通知相关订阅者。熟悉设计模式的朋友应该了解这与23种设计模式中的观察者模式极为相似。

同样,Redis的pub/sub是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者之间的耦合,  Redis作为一个pub/sub的server, 在订阅者和发布者之间起到了消息路由的功能。

  如果没听懂上述的专业解释,没关系,其实我也没太听懂。

  简单来讲,这里面还有个channel的概念,这里就是频道的意思,比如你订阅了银行的频道,当你的资金发生变动时,银行就会通过它的频道给你发送信息,在这里,你是属于被动接收的,而不是向银行索要信息,这个例子中,你就是sub(订阅者),而银行就是pub(发布者)。

项目运用场景:

  一直都认为你会一样技术之前,都必须先明白这样一种技术在哪些地方会被用到,不能盲目的学东西。

  看到发布订阅的特性,用来做一个简单的实时聊天系统再适合不过了。这是其中之一,当然这样的东西,我们开发中很少涉及到。再举一个常用的,在我们的分布式架构中,常常会遇到读写分离的场景,在写入的过程中,就可以使用redis发布订阅,使得写入值及时发布到各个读的程序中,就保证数据的完整一致性。再比如,在一个博客网站中,有100个粉丝订阅了你,当你发布新文章,就可以推送消息给粉丝们拉。总之场景很多,需要去挖掘。。

回顾java如何操作redis:

  redis是一种缓存数据库,它也是C/S的结构,也就是客户端和服务端,一般来说,在java中,我们通常使用 jedis(客户端)去操作redis(服务端),这其中操作的时候,两者之间肯定要建立连接,就像数据库链接一样,在关系型数据库中,我们一般都维护一个连接池,以达到链接的复用,来省去建立连接和关闭连接的时间。所以在jedis中,同样也存在一个jedispool(jedis连接池)的概念,我们都是从池中去取连接使用。

上代码:

想使用jedis先引入依赖

  1. <dependency>
  2. <groupId>redis.clients</groupId>
  3. <artifactId>jedis</artifactId>
  4. <version>2.9.0</version>
  5. </dependency>

建立一个Publisher (发布者)

  1. public class Publisher extends Thread{
  2.  
  3. private final JedisPool jedisPool;
  4.  
  5. public Publisher(JedisPool jedisPool) {
  6. this.jedisPool = jedisPool;
  7. }
  8.  
  9. @Override
  10. public void run() {
  11. BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
  12. Jedis jedis = jedisPool.getResource(); //连接池中取出一个连接
  13. while (true) {
  14. String line = null;
  15. try {
  16. line = reader.readLine();
  17. if (!"quit".equals(line)) {
  18. jedis.publish("mychannel", line); //从 mychannel 的频道上推送消息
  19. } else {
  20. break;
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. }

再建立一个订阅者

  1. public class Subscriber extends JedisPubSub {
  2.  
  3. public Subscriber(){}
  4. @Override
  5. public void onMessage(String channel, String message) { //收到消息会调用
  6. System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
  7. }
  8. @Override
  9. public void onSubscribe(String channel, int subscribedChannels) { //订阅了频道会调用
  10. System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
  11. channel, subscribedChannels));
  12. }
  13. @Override
  14. public void onUnsubscribe(String channel, int subscribedChannels) { //取消订阅 会调用
  15. System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
  16. channel, subscribedChannels));
  17.  
  18. }
  19. }

这里订阅者需要继承JedisPubSub,来重写它的三个方法。用途 注释上已经写了,很简单。

我们这里只是定义了一个订阅者,下面去订阅频道。

  1. public class SubThread extends Thread {
  2.  
  3. private final JedisPool jedisPool;
  4. private final Subscriber subscriber = new Subscriber();
  5.  
  6. private final String channel = "mychannel";
  7.  
  8. public SubThread(JedisPool jedisPool) {
  9. super("SubThread");
  10. this.jedisPool = jedisPool;
  11. }
  12.  
  13. @Override
  14. public void run() {
  15. System.out.println(String.format("subscribe redis, channel %s, thread will be blocked", channel));
  16. Jedis jedis = null;
  17. try {
  18. jedis = jedisPool.getResource(); //取出一个连接
  19. jedis.subscribe(subscriber, channel); //通过subscribe 的api去订阅,入参是订阅者和频道名
  20. } catch (Exception e) {
  21. System.out.println(String.format("subsrcibe channel error, %s", e));
  22. } finally {
  23. if (jedis != null) {
  24. jedis.close();
  25. }
  26. }
  27. }
  28. }

最后,再写一个测试类去跑一下。键盘输入消息,订阅者就会触发onMessage方法

  1. public class PubSubDemo {
  2.  
  3. public static void main( String[] args )
  4. {
  5. // 连接redis服务端
  6. JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379);
  7.  
  8. System.out.println(String.format("redis pool is starting, redis ip %s, redis port %d", "127.0.0.1", 6379));
  9.  
  10. SubThread subThread = new SubThread(jedisPool); //订阅者
  11. subThread.start();
  12.  
  13. Publisher publisher = new Publisher(jedisPool); //发布者
  14. publisher.start();
  15. }
  16. }

看打印结果

java实现 redis的发布订阅(简单易懂)的更多相关文章

  1. redis(3)发布订阅

    一.发布/订阅模式 在软件工程里面,发布/订阅是一种消息模式,这种模式旨在将消息发送者和消息接收者解耦.发送者不需要关心将消息发送给谁,接收者也不需要知道消息的发送者是谁.发送者将消息发布以后就结束动 ...

  2. Redisson 分布式锁实现之前置篇 → Redis 的发布/订阅 与 Lua

    开心一刻 我找了个女朋友,挺丑的那一种,她也知道自己丑,平常都不好意思和我一块出门 昨晚,我带她逛超市,听到有两个人在我们背后小声嘀咕:"看咱前面,想不到这么丑都有人要." 女朋友 ...

  3. redis的发布订阅模式

    概要 redis的每个server实例都维护着一个保存服务器状态的redisServer结构 struct redisServer {     /* Pubsub */     // 字典,键为频道, ...

  4. StackExchange.Redis 使用-发布订阅 (二)

    使用Redis的发布订阅功能 redis另一个常见的用途是发布订阅功能 . 它非常的简单 ,当连接失败时 ConnectionMultiplexer 会自动重新进行订阅 . ISubscriber s ...

  5. redis 实现发布订阅的功能

    redis 除了作为缓存的功能外还可以用作消息中间件的功能,这片博客主要是介绍一下 redis 整合spring 实现消息的发布和订阅功能: 1:redis依赖,依赖两个包,redis 包, spri ...

  6. [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐

    [翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...

  7. 【spring boot】【redis】spring boot 集成redis的发布订阅机制

    一.简单介绍 1.redis的发布订阅功能,很简单. 消息发布者和消息订阅者互相不认得,也不关心对方有谁. 消息发布者,将消息发送给频道(channel). 然后是由 频道(channel)将消息发送 ...

  8. netty-socketio(二)整合redis实现发布订阅

    1.Redis 发布订阅 参考:https://www.runoob.com/redis/redis-pub-sub.html Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub ...

  9. .net core 使用Redis的发布订阅

    Redis是一个性能非常强劲的内存数据库,它一般是作为缓存来使用,但是他不仅仅可以用来作为缓存,比如著名的分布式框架dubbo就可以用Redis来做服务注册中心.接下来介绍一下.net core 使用 ...

随机推荐

  1. mysql根据汉字首字母排序[转]

    select  areaName  from area order by   convert(areaName USING gbk)   COLLATE   gbk_chinese_ci asc 说明 ...

  2. JDK 中的设计模式应用实例

      在 JDK(Java Development Kit)类库中,开发人员使用了大量设计模式,正因为如此,我们可以在不修改 JDK 源码的前提下开发出自己的应用软件.研究 JDK 类库中的模式实例也不 ...

  3. 关于flying框架

    开发10多年了,开发过程中遇到的最大的问题: ①项目的代码越来越多了,越来越复杂了,而客户的需求,你还不得不往里面加入新代码. ②开发了很多项目,每次复用时却只能把代码copy来copy去,然后调试. ...

  4. Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析

    学习Java并发编程不得不去了解一下java.util.concurrent这个包,这个包下面有许多我们经常用到的并发工具类,例如:ReentrantLock, CountDownLatch, Cyc ...

  5. java类路径classpath和包

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  6. 如何为form表单的button设置submit事件

    若button按钮没有type属性,浏览器默认按照type=submit逻辑处理,这样若将没有type的button放在form表单中,点击按钮就会执行form表单提交

  7. redis info详解

    INFO 以一种易于解释(parse)且易于阅读的格式,返回关于 Redis 服务器的各种信息和统计数值. 通过给定可选的参数 section ,可以让命令只返回某一部分的信息: server 部分记 ...

  8. [codility] Lession1 - Iterations - BinaryGap

    Task1: A binary gap within a positive integer N is any maximal sequence of consecutive zeros that is ...

  9. 05_Linux网络配置及CRT远程

    占位占位占位占位占位占位占位占位

  10. 基于 React + Webpack 的音乐相册项目(上)

    笔记仓库:https://github.com/nnngu/LearningNotes 上一篇文章用爬虫自动下载了一些图片,这一篇就用这些图片做一个音乐相册吧! 效果预览 点击图片,切换到背面: 演示 ...