需求:
这个功能开发的直接需求是为了提醒操作员即使处理库位补货, 在用户操作分拣波次操作以后, 会出现有库位库存为负数, 这种情况下需要有消息通知机制通知相关人员对相应库位进行补货处理;
1. 通知实体: 被通知的用户实体可能是具体到某些登录用户, 也可能是某些Role 下的用户
2. 通知状态: 消息窗口会采用浮动窗口告知用户有N条记录未读, 以及未读消息摘要; 消息在被用户阅读之前是未读状态, 读取以后会改变状态为已读状态; 消息窗口不会通知用户已读消息。
3. 消息定制: 应该提供能力供实施部门方便的定制一些业务规则, 来添加简单的新的消息类型和新的消息产生机制, 比如实施部门可以配置定时任务扫描DB中的业务表, 根据规则发现异常数据, 并把相关信息以消息形式发送给WMS 客户端;
设计:
总体设计
客户端如何获取消息:
主流的方式无法长连接推送和客户端轮询的拉取的方式, 为了简化Server 和客户端的开发复杂度, 我们选择了客户端轮询的方式, 这样可以直接沿用我们WMS 中已有的WebService 接口的方式来暴露消息;
存储:
消息体:
考虑到通知消息属于非核心业务, 并且对轮询的方式会产生大量的请求, 所以我们不打算使用DB 做消息的存储, 以减少大量低优先级的db 访问来拖累DB 性能和稳定性;所以我们采用redis 来存储每个订阅者订阅的消息;
消息订阅定义:
要实现消息订阅的可配置, 需要对消息类型, 仓库, 订阅者进行关联, 这些信息存储在DB中, 在系统启动的时候会把这些信息Load 到redis 中, 后续的界面操作针对这个数据的增删改会同步修改redis 中的缓存数据;
数据格式:
1. 客户端访问App Server的接口是以xml 格式的方式进行对接;
2. Server 内部存储在Redis 中的数据以protobuf 的格式进行序列化和反序列化;具体在实现上使用Protostuff 生成protobuf runntime schema 对java 对象notification 进行序列化反序列化
数据结构
1. DB
消息订阅定义:
已有表添加数据:
GV_SYS_CODECLASS 中添加 code = 'SUBSCRIBE_TYP', CNCATEGROYNAME = '订阅类别的记录'
GV_SYS_CODEINFO 中添加 code = 'REP_NOTICE', CNCATEGROYNAME = '补货通知', codeclass_id = #1 中的ID 的记录
创建新表 GV_SUBSCRIBER
CREATE TABLE GV_SUBSCRIBER
( "ID" NUMBER(19,0) NOT NULL ENABLE,
"WHID" NUMBER(19,0),
"SUBSCRIBERID" VARCHAR2(255 CHAR),
"SUBSCRIBERTYPE" VARCHAR2(255 CHAR),
"MESSAGETYPE_ID" NUMBER(19,0),
PRIMARY KEY ("ID")
)
2. Redis
Redis 中存储的
WMS_SUBSCRIBERS -->Set of subscriber
WMS_SUBSCRIBER_TYPE _$messageTypeId_$whID --> Set of subscriber
WMS_SUBSCRIBERED_MESSAGES_$subscriberId_$whID --> Ordered set of notification
以 “WMS_SUBSCRIBERS” 为key 存储 Subscriber 集合, 这个集合的目的是为了能够取到当前系统中所有subscriber, 然后可以遍历 WMS_SUBSCRIBERED_MESSAGES_$subscriberId_$whID 键值列表, 删除每个键值所对应的有序集合中的过期通知; WMS_SUBSCRIBER_TYPE _$messageTypeId_$whID 键值对存储的是从表GV_SUBSCRIBER 中加载的订阅者集合, 每种类型的通知在每个仓库中的订阅者(User 或Role)
其中WMS_SUBSCRIBERED_MESSAGES_$subscriberId_$whID 往Ordered Set 中新增element 的时候以该notification 当前产生的时间戳为排序字段;
接口
1.通知消息产生:
通知消息产生的业务方需要知道当前消息的通知类别ID 和需要发送的逻辑仓库ID
测试用例中的模拟代码如下:
Notification notice = new Notification();
notice.setId(UUID.randomUUID().toString());
notice.setTitle("消息标题" + dateformat.format(new Date()));
notice.setBody("消息体");
notice.setCreateTime(System.currentTimeMillis()); notice.setExpireTime(60*30);
notice.setWhId(119240L);
notice.setMessageTypeId(124719L);
nManager.addNotice(notice);
NotificationManager 会从redis 缓存中获取 WMS_SUBSCRIBER_TYPE _$messageTypeId_$whID所对应的所有Subscriber,然后会针对每一个Subscriber 调用redis 接口
向有序集合 WMS_SUBSCRIBERED_MESSAGES_$subscriberId_$whID --> Ordered set of notification 中添加Notfication
2. 前端消息获取:
接口: PackNotificationVo listNotifications(
ClientProperty clientProperty, Long whId, List<Long> subscriberIdList, Long lastFetchTimeStamp)
客户端程序需要维护 whid, lastFetchTimeStamp 信息在本地, 每次请求把这个时间戳信息发送给服务器端,
客户端行为的伪代码就是
lastFetchTimeStamp = get($whid);
$newTimeStamp = 新的时间戳;
if($lastFetchTimeStamp& ==null ) $lastFetchTimeStamp = 默认的当前时间- 3天
call Server
展示新消息
set ($whid, 返回Notification 对象列表中创建时间最大的时间戳 )
服务器端的行为会把Notification在给定时间戳之后的 Ordered set 中的元素返回给客户端
过期消息删除
过期消息删除使用定时任务, 根据给定TTL, 即时出当前时间减去TTL 的时间得到超时时间点, 在这个时间点之后的Notification 都应该被删除;
maxScore = nowTimeStamp - TTL ;
shardedJedis.zremrangeByScore(WMS_SUBSCRIBERED_MESSAGES_$subscriberId_$whID, 0D, maxScore);
分享到:
相关推荐
基于Redis和Mysql的存储系统的设计与实现,范东媛,钮心忻,本文基于Redis和Mysql数据库设计并且实现了在线学习平台的数据存储系统。利用Mysql的持久化存储和Redis的高速读写设计出具有存储数据庞�
分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。...
100讲带你实战基于Redis的高并发,学习笔记
100讲带你实战基于Redis的高并发预约抢购系统
保证能跑通-基于Redis Zset实现排行榜功能的源码,包含页面,接口,下载运行即可访问,步骤请阅读README.MD文件
基于Redis方式实现分布式锁
主要介绍了Java基于redis实现分布式锁代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
毕业设计+Python基于Scrapy+Redis分布式爬虫设计+源码案例+Python + Scrapy + redis 毕业设计+Python基于Scrapy+Redis分布式爬虫设计+源码案例+Python + Scrapy + redis 毕业设计+Python基于Scrapy+Redis分布式爬虫...
基于redis分页和排序设计(根据redis的数据类型设计)
基于redis实现的分布式session控制,多站点 多服务器均可兼容,使用方法:本地启动redis并配置到webconfig中
基于redis单点登录解决方案。使用redis的key时效性代替session对多个相同进行统一管理。代码包括3个项目master、projectServlet、projectSpring,其中master是登录主项目,其他两个是次项目。只要在master登录就可以...
基于redis实现的单点登录这套方案比SSO CAS来说比较简单,容易上手,主要是依赖每个应用的拦截器和redis实现单点登录。
在应用系统当中,需要确保数据访问所具备的时效性, 将关键性的业务数据全都存储在内存当中。不过如果出现业务 范围持续拓展的情况,只是...作出相应的设计以及改造,让系统架构呈现出更为优质的可扩 展性、可靠性。
主要介绍了Mybatis-plus基于redis实现二级缓存过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
基于Redis集群的分布式会话管理系统的设计与实现 ,蒋亮亮,卞佳丽,随着互联网的发展,网站的页面浏览量和访问人数与日俱增。为了使web应用能适应大规模的访问,需要使用分布式集群来部署应用。实现
Python毕业设计 基于Redis博客系统设计与实现源码+详细文档+全部资料(高分项目).zipPython毕业设计 基于Redis博客系统设计与实现源码+详细文档+全部资料(高分项目).zip 【备注】 1、该项目是个人高分毕业设计...
系统在运行过程中,如遇上某些活动,访问的人数会在一瞬间内爆增,导致服务器瞬间压力飙升,使系统超...本文介绍php基于redis,使用令牌桶算法,实现访问流量的控制,提供完整算法说明及演示实例,方便大家学习使用。
scrapy-redis, 基于Redis的组件组件 scrapy 基于redis的组件组件。自由软件:MIT许可证文档:https://scrapy-redis.readthedocs.org 。python 版本:2.7,3.4 特性分
SpringBoot基于redis的分布式锁,有word使用文档,根据文档配置即可使用
内容概要:通过带着读者基于 Redis 分布式消息队列的报文过滤系统的设计与实现过程做了详尽细致的描述。依据 ActiveMQ、Redis、Java、Mybatis 等计算机技术,结合业务分离的项目设计理念和主备部署服务的特点,本...