【记录】java 实现 “消息回复率”

本贴最后更新于 2468 天前,其中的信息可能已经物是人非

规则:用户 A 给用户 B 发送一条消息,24 小时内如果 B 回复了 A,给 B 增加消息回复率,超过 24 小时则扣回复率。

只拿一个月的回复数据计算,回复率初始值(用户未)为0%。

从消息服务器,拿到俩个用户的 id,利用 redis 做会话锁。

思路:比如用户 A 给用户 B 发送一条消息,key 值设置为 A-B,value 为当前时间的时间戳,从 redis 中查询 key 值 A-B 或者 B-A 是否存在。

如果 A-B 存在,不存入 reids,因为 A 已经给 B 用户发送过信息,只计算 A 给 B 发送第一条消息的时间。

如果 B-A 存在,属于 B 用户回复 A 用户的信息,不存入 redis

利用 spring schedule 定时,每隔一段时间取出 redis 会话锁中所有 key,判断时间戳是否超过 24 小时。

超过 24 小时,根据时间戳查询数据源,24 小时内有没有 B 回复给 A 的消息记录。

存在消息记录,存入数据源,表结构:发送者 id,接受者 id,回复状态,时间戳,删除 redis 中会话锁,以便计算 24 小时后用户回复率。之后根据这张表,计算回复率就可以了。数据源我用的 mongoDB。

(会话锁也可以利用 MQ 的延时消息来实现,这样的好处是不依赖定时任务,也避免了每次查 redis,那些时间不够 24 的 key 的消耗。)

/** * 计算消息回复率 */ public void createSessionLock(IMRouteResponse imRouteResponse){ //发送人id String sendId = imRouteResponse.getFromAccount(); //接受人id String taskId = imRouteResponse.getTo(); // 查询会话是否已存在 final String key = sendId + "-" + taskId; final String reverseKey = taskId + "-" + sendId; if(!redisTemplate.hasKey(Constants.MESSAGE_REPLY_RATE_LOCK + key) && !redisTemplate.hasKey(Constants.MESSAGE_REPLY_RATE_LOCK + reverseKey)){ // 不存在 创建会话 redisTemplate.opsForValue().set(Constants.MESSAGE_REPLY_RATE_LOCK + key,System.currentTimeMillis()+""); logger.info("【消息回复率】创建{}会话",key); }else{ // 已存在什么都不做 logger.info("【消息回复率】会话{}已存在!放弃创建会话!",key); } }


定时器

/** * 每天计算消息回复率 */ @Scheduled(cron = "0 0 0/1 * * ?") public void messageReplyRate(){ userMessageReplyRateService.messageReplyRate(); }

/** * 拿出会话锁中,计算超过24小时的会话的回复率情况 */ public void messageReplyRate(){ Set<String> sessionKey = redisTemplate.keys(Constants.MESSAGE_REPLY_RATE_LOCK + "*"); for (String keyJson : sessionKey) { String timeJson = redisTemplate.opsForValue().get(keyJson); // 此时间+24小时是否超过 当前时间 long currentTimeMillis = System.currentTimeMillis(); Long start = Long.valueOf(timeJson) + (1000 * 60 /* 24*/); if(start < currentTimeMillis){ //MESSAGE_REPLY_RATE_LOCK:12-62 String[] split = keyJson.split(":"); //12-62 String key = split[1]; String[] split1 = key.split("-"); // 查询mongo 收信人在 timeJson 之后 有没有给发件人 回复 String send = split1[0]; String task = split1[1]; // 查询 接收方之后的24小时里有没有给发送方 回信息 logger.info("【消息回复率】id:" + send + "用户给id:" + task + "用户发送的消息已超过24小时。"); ReturnConstants rc = imHistoryRecordService.queryHistoryByUserAndTime(task, send, Long.valueOf(timeJson)); if(ReturnConstants.SUCCESS == rc){ //删除会话锁 redisTemplate.delete(Constants.MESSAGE_REPLY_RATE_LOCK + key); }else{ //这条记录没被正确保存mongo,判断一下 如果时间戳超过 26小时,意味着它失败了两次,就删掉吧。 if((NumberUtils.toInt(timeJson) + (1000 * 60 * 26) > currentTimeMillis)){ redisTemplate.delete(Constants.MESSAGE_REPLY_RATE_LOCK + key); } } } }

/** * 查询历史记录,这个时间段之后的24小时,双方之间有没有通信 * @param send * @param task * @param currentTimeMillis */ public ReturnConstants queryHistoryByUserAndTime(String send, String task, long currentTimeMillis) { logger.info("【消息回复率】查询mongo,发送人Id:{},接受人id:{},在{}后24小时中。",send,task, Dates.formatTimeMillis(currentTimeMillis,"yyyy-MM-dd HH:mm:ss")); Criteria criteria = new Criteria(); criteria.and("fromAccount").is(send); criteria.and("to").is(task); //条件查询2,gte大于 lte小于 criteria.and("msgTimestamp").gte(currentTimeMillis).lte(currentTimeMillis + 1000 * 60 * 24); Query query = new Query(criteria); long count = mongoTemplate.count(query, IMRouteResponse.class); UserMessageReplyRate umrr = new UserMessageReplyRate(); if(count > 0){ // 双方有过通信 umrr.setReplyUserId(NumberUtils.toInt(task)); umrr.setToUserid(NumberUtils.toInt(send)); umrr.setState(1);//是否回复成功 1:回复者回复了消息 2:回复者没有回复消息 umrr.setTimeline(System.currentTimeMillis()); logger.info("【消息回复率】回复人id{},被回复人id{},在24小时内,回复了消息"); }else{ umrr.setReplyUserId(NumberUtils.toInt(task)); umrr.setToUserid(NumberUtils.toInt(send)); umrr.setState(2);//是否回复成功 1:回复者回复了消息 2:回复者没有回复消息 umrr.setTimeline(System.currentTimeMillis()); logger.info("【消息回复率】回复人id{},被回复人id{},在24小时内,没有回复消息"); } return imUserMessageReplyService.saveUserMessageReplyRate(umrr); }

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1062 引用 • 3455 回帖 • 137 关注
  • 回复率
    1 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    25 引用 • 373 回帖
  • CodeMirror
    2 引用 • 17 回帖 • 187 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    381 引用 • 1875 回帖 • 1 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1340 回帖
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    108 引用 • 153 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    948 引用 • 1460 回帖
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    29 引用 • 306 回帖
  • SMTP

    SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。

    4 引用 • 18 回帖 • 651 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 2 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 353 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 669 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    84 引用 • 414 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 451 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    45 引用 • 44 回帖 • 1 关注
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    167 引用 • 597 回帖 • 3 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 19 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 513 关注
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    5 引用 • 16 回帖 • 6 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 535 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 568 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖 • 1 关注
  • 导航

    各种网址链接、内容导航。

    45 引用 • 177 回帖
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    125 引用 • 370 回帖
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    8 引用 • 37 回帖 • 1 关注