Redis的发布与订阅

业务:

运用数据与信息指导小药工的采购生产与销售行为

需求背景:

(1)药工汇小程序用户(即小型中药初加工用户)需要知道自己加工的品种的价格涨跌信息和品种相关资讯)

需求分析拆解:

(1)使用爬虫程序脚本从中药材天地网上爬取价格和资讯相关信息(爬虫)

(2)此爬虫程序的执行使用定时任务管理(定时任务)

(3)爬虫获取的信息持久化到mongodb数据库(数据持久化)

(4)药工汇得到的信息的过程使用发布订阅模型,每个指向相同Redis主机数据库的连接为一个订阅者或发布者,一级分发频道为平台名称,二级分发频道为品种名称,订阅者无需点击订阅,订阅是根据主营品种自动默认完成订阅的(发布与订阅)

(5)统一调度守护程序轮询所有消息,根据频道将信息使用消息模板分发到每个订阅者,这样,此守护进行长时间占用CPU,效率低;可以改为使用定时任务,例如8:00-20:00每隔1小时执行一次消息轮询脚本;使用微信服务号的模板消息向用户推送信息(统一调度轮询守护进程)

技术理论:

1. 观察者模式与发布订阅模型的区别

(1)观察者模式图解

Redis的发布与订阅

(2)发布-订阅模型图解

Redis的发布与订阅

(3)两者的区别

a. 从图解中可以看出,观察者模式没有调度中心作为中转,直接将观察者注册到目标,发生事件时目标直接更新通知观察者; 发布订阅模型则以调度中心作为中转,订阅者将事件注册到调度中心,发生事件时发布者将信息发送给调度中心进行统一调度,调度中心将信息推送给订阅者

b. 相对来说,观察者模式是存在依赖的;发布订阅模型是松耦合的

2. 发布订阅与RestAPI的优缺点场景对比

(1)发布订阅的优缺点及场景

发布订阅本质上是服务器(发布者)向客户端(订阅者)反向推送的机制;

优点:

a. 是达到了最高的实时性,因为服务器数据的更新同时推向了客户端;

b. 一次性为单条数据同步

c. 采用事件回调的方式更新数据,总体上是异步的

缺点:

a. 是用户可能会很烦,因为用户是被动接收的(即使是用户根据标签,用户自己订阅的,用户依然可能会很烦),而且信息很可能不是精准用户想要的信息;

b. 每更新一条数据则同步一次,同步次数频繁

场景:

是用户迫切需要某一标签的信息或者数据

(2)RestAPI的优缺点及场景

RestAPI本质上是客户端向服务端正向请求的机制,原理和发布订阅刚好相反;

优点:

a. 是客户端根据自己的意愿请求数据,得到的信息是精准的;

b. 一次性同步一个时间段内所有数据, 体现为数据同步的批量操作

c. 采用主动同步请求的方法,是同步的

缺点:

是没有发布订阅的高实时性,不过一般来说,用户不需要这么高的实时性;

场景:

是通用情况

例如:下面的信息平台和药工汇平台数据同步的方案比较

Redis的发布与订阅

 
方案  详细说明  特点  需要做什么
方案1:使用发布订阅模型同步更细数据

信息平台已经向频道发布数据,

需要做的是在时间回调函数中 调用药工汇平台提供的RestAPI,此RestAPI的内容为更新药工汇的数据,

为INSERT操作,PUT操作;

1. 及时同步

2. 异步执行

3. 单条多批次同步

4. 事件触发

1. 只需药工汇平台提供RestAPI, 此RestAPI为PUT操作,INSERT操作;

需传入的参数有访问药工汇平台的平台级access_token,药工汇平台做access_token验证;

需关心药工汇平台数据库结构(主要工作在药工汇)

方案2:使用定时任务请求RestAPI获取数据

信息平台已经向频道发布数据,

需要做的是使用定时任务跨域请求 信息平台提供的RestAPI,此RestAPI的内容为从频道中获取数据,

为SELECT操作, LIST操作

1. 延时同步

2. 同步执行

3. 批量同步

4. 定时任务触发

1. 只需信息平台提供RestAPI,此RestAPI为LIST操作,SELECT操作;

需传入的参数有访问信息平台的平台级access_token,信息平台做access_token验证;

无需关系药工汇平台数据库结构;药工汇配置定时任务(主要工作在信息平台)

2. Redis中发布订阅的架构

(1)图解

Redis的发布与订阅

包括:

a. 订阅者订阅一个或多个频道

b. 订阅者使用模式匹配订阅多个频道

c. 订阅者取消订阅频道

d. 发布者向某个频道发布消息

3. Redis的发布订阅实验(验证已订阅的客户端是否会自动收到消息)

预期:

Redis-client_2在步骤(2)不会收到消息

Redis-client_2在步骤(3)不会收到消息

Redis-client_2在步骤(4)收到消息

步骤:

(1)启动Redis服务器和两个Redis客户端:启动Redis-server,启动Redis-client_1和Redis-client_2

Redis的发布与订阅

结果:服务器和两个客户端已经成功启动

(2)在Redis-client_1向频道channel_1发送一条消息,消息内容为 "Hello, Word!"; 观察Redis-client_2是否收到此消息

Redis的发布与订阅

结果:客户端2未订阅任何频道则无法收到消息

(3)在Redis-client_2订阅频道channel_1; 观察Redis-client_2是否收到消息Hello,World!

Redis的发布与订阅

结果:客户端2订阅了频道1无法收到订阅前发送到频道1的任何消息

(4)在Redis-client_1向频道channel_1发送一条消息,消息内容为 "Good afternoon!"; 观察Redis-client_2是否收到此消息

Redis的发布与订阅

结果:客户端2能收到订阅后发送到此频道的任何消息

结论:实验结果和预期猜想相符,Redis客户端只能被动接收到订阅此频道发送的消息

4. Redis发布订阅实验(原生PHP+php_redis扩展)

准备:

(1)安装好php_redis扩展(在windows上需要下载php_redis.dll并放入php/extra中;在php.ini中加入extension=php_redis.dll)

注意:

a. 下载php_redis.dll对应版本时需要查看phpinfo中php的版本,php是32位还是64位的,php的thread是否为safety

b. 需要将extension=php_redis.dll放入apache/php.ini和php/php.ini中

(2)启动Redis服务器及启动Redis客户端1

(3)编写Redis客户端2订阅的脚本,如下:

<?php
//避免在默认的配置下,1分钟后终端了与redis服务器的链接
ini_set('default_socket_timeout', -1);
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$redis->subscribe(['channel_1'], function($redis, $channel, $msg){
    var_dump($redis);
    var_dump($channel);
    var_dump($msg);
});
?>

启动脚本运行,并在客户端1发送一条消息,观察客户端2:

Redis的发布与订阅

3. 其他发布订阅框架例如ActiveMQ与 Redis的区别

平台交互图:

Redis的发布与订阅

编码实现:

服务器运维:

参考:

1. 观察者模式与发布订阅模式的区别

https://www.cnblogs.com/lovesong/p/5272752.html

2. Redis的发布订阅机制

https://www.cnblogs.com/yitudake/p/6747995.html

上一篇:一个input标签搞定含内外描边及阴影的按钮~


下一篇:一种思路,隐藏input标签,通过label关联