如何实现设备组缓存的正确清除?——基于心跳请求和心跳响应的解决方案

这篇具有很好参考价值的文章主要介绍了如何实现设备组缓存的正确清除?——基于心跳请求和心跳响应的解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在设备组关闭后,如何保证缓存中的设备组信息能够正确清除?本文将介绍如何通过前端实现设备组心跳检测和缓存清除,以及通过后端实现缓存清除的逻辑来解决该问题。我们还将详细讨论如何利用心跳请求和心跳响应来实现设备组缓存的正确清除,并提供基于Vue和SpringBoot的代码示例。

一、问题描述

在开发设备管理系统时,我们经常需要保证设备组在关闭后能够从缓存中正确删除,以避免占用过多的系统资源。

示例:若依前后端分离框架,如果用户使用当前设备组,那么当前设备组会被写进缓存里,然后被占用,其他用户则不能使用该设备组;如果用户退出当前设备组,那么将从缓存里删掉该设备,但是很难保证的情况是,如果用户突然关闭浏览器,或者不正常关闭页面、退出帐号,都不能正常从缓存里删除该设备组,如何保证不管怎么样退出,都能从缓存中删掉该设备组?

二、问题分析

前端使用一个定时器,每隔5秒向后端发送请求,告知后端当前设备组是否还在使用中。后端使用一个DEVICE_GROUP_KEY + id来保存设备组是否被占用的状态,当用户加入设备组时,将该设备组的状态设置为占用,并设定过期时间为10秒;当用户退出设备组时,从DEVICE_GROUP_KEY + id中删除该设备组的状态。如果后端收到了一段时间内没有收到定时器请求的设备组,就会自动将该设备组从DEVICE_GROUP_KEY + id中删除。

当用户正常退出设备组时,前端会清除定时器并向后端发送请求,告知后端该设备组已经退出使用。如果用户异常退出设备组,则后端会在一段时间后自动删除该设备组。

三、解决方案

你的前端代码看起来已经调用了后端接口将设备组放入缓存中了。如果你想实现定时向后端发送请求,告知后端该设备组是否还在使用中,可以使用setInterval函数创建一个定时器,每隔一定时间向后端发送请求,告知后端该设备组仍在使用中。

前端

deviceInfo是预选设备组,currentDeviceInfo是当前设备组,deviceGroupKeys是缓存中的设备组,代码示例如下:

<template>
  <div>
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="60px">
      <el-form-item label="设备组" prop="group">
        <el-select v-model="deviceGroup" placeholder="请选择" @change="selectDeviceGroup">
          <!-- 选择deviceGroupList -->
          <el-option v-for="item in deviceGroupList" :key="item.deviceGroup" :label='"第" + item.deviceGroup + "组"'
            :value="item.deviceGroup" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-circle-check" size="mini" @click="joinDeviceGroup">确定</el-button>
        <el-button icon="el-icon-remove-outline" size="mini" type="info" @click="leaveDeviceGroup">退出当前设备组</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
    /** 加入设备组 */
	async joinDeviceGroup(){
	//查询预选的设备组是否被占用
	if (this.deviceGroupKeys.includes(`${this.deviceInfo.deviceGroup}`)) {
	        this.$message({
	          message: "该设备组已被使用",
	          type: "warning",
	        });
	        return;
	      }
	      //预选设备组没有被占用,如果当前设备组被自己占用,则将其从缓存中删除
	      if (this.currentDeviceInfo.deviceGroup !== "") {
	        await deleteDeviceGroupKey(this.currentDeviceInfo.deviceGroup);
	        clearInterval(this.timer);
	      }
	      //否则将deviceInfo预选设备组放入currentDeviceInfo当前设备组
	      this.currentDeviceInfo = JSON.parse(JSON.stringify(this.deviceInfo)) || null;
	      // 将currentDeviceInfo中的deviceGroup放入缓存,用setDeviceGroupKey方法
	      await setDeviceGroupKey(this.currentDeviceInfo.deviceGroup);
	      // 开启定时器
	      this.setInterval();
	}
    /** 定义一个定时器,每隔5秒钟,调用一次sendDeviceHeartbeat方法 */
    setInterval() {
      // 如果currentDeviceInfo.deviceGroup为空,则停止定时器
      if (this.currentDeviceInfo.deviceGroup == "") {
        clearInterval(this.timer);
      } else {
        this.timer = setInterval(() => {
          this.sendDeviceHeartbeat();
        }, 5000);
      }
    },

    // 发送心跳请求的函数
    sendDeviceHeartbeat() {
      // 如果this.currentDeviceInfo.deviceGroup为空,则停止定时器
      if (this.currentDeviceInfo.deviceGroup == "") {
        clearInterval(this.timer);
      }
      // 发送请求deviceHeartBeat
    deviceHeartBeat(this.currentDeviceInfo.deviceGroup).then((response) => {
        // console.log(response);
        if (response === 0) {
          // 心跳成功,设备组仍在使用中
        } else {
          // 心跳失败,设备组已经退出使用
          this.$message({
            message: "设备组已经退出使用",
            type: "warning",
          });
          clearInterval(this.timer);
        }
      });
    },

然后在用户正常退出设备组时,清除定时器并向后端发送请求,告知后端该设备组已经退出使用。代码示例如下:

leaveDeviceGroup() {
      if (this.currentDeviceInfo.deviceGroup != "") {
        deleteDeviceGroupKey(this.currentDeviceInfo.deviceGroup).then((response) => {
          //清空currentDeviceInfo
          this.currentDeviceInfo = {
            deviceGroup: "",
          };
        });
      }
      // 停止定时器
      clearInterval(this.timer);
}

计时器应该在用户正常退出设备组和关闭页面时被清除。在Vue中,可以通过在beforeDestroy()生命周期钩子中清除计时器,例如:

beforeDestroy() {
  clearInterval(this.timer);
}

这里假设你的计时器是通过setInterval()创建的,并将其存储在Vue实例的timer属性中。当Vue实例被销毁时,beforeDestroy()生命周期钩子会被调用,此时可以清除计时器。

后端

获取缓存中deviceGroup所有的key

    /**
     * 获取缓存中deviceGroup所有的key
     */
    @GetMapping("/getDeviceGroupKeys")
    public List<Integer> getDeviceGroupKeys() {
        //将redis中device_group的的基本对象列表,使用redisCache.keys()方法获取
        String[] keys = redisCache.keys(CacheConstants.DEVICE_GROUP_KEY + "*").toArray(new String[0]);
        //将keys中的值,去掉前缀,只保留1,2,3,4,5
        List<Integer> list = new ArrayList<>();
        for (String key : keys) {
            list.add(Integer.parseInt(key.substring(CacheConstants.DEVICE_GROUP_KEY.length())));
        }
        //将list从小到大排序
        list.sort((o1, o2) -> o1 - o2);
        return list;
    }

实现将设备组放入缓存

    /**
     * 将设备组放入缓存
     */
    @GetMapping(value = "/setDeviceGroupKey/{id}")
    public String setDeviceGroupKey(@PathVariable("id") Integer id) {
        redisCache.setCacheObject(CacheConstants.DEVICE_GROUP_KEY + id, "true", 10, TimeUnit.SECONDS);
        return redisCache.hasKey(CacheConstants.DEVICE_GROUP_KEY + id) ? "true" : "false";
    }

在用户正常退出设备组时,你可以实现一个deleteDeviceGroupKey接口,用于从缓存中删除该设备组。代码示例如下:

    /**
     * 将设备组从缓存中删除
     */
    @GetMapping("/deleteDeviceGroupKey/{id}")
    public String deleteDeviceGroupKey(@PathVariable("id") Integer id) {
        redisCache.deleteObject(CacheConstants.DEVICE_GROUP_KEY + id);
        return redisCache.hasKey(CacheConstants.DEVICE_GROUP_KEY + id) ? "false" : "true";
    }

你可以实现一个deviceHeartBeat接口,用于更新设备组在缓存中的存活时间。代码示例如下:

    /**
     * 检查设备组是否还在使用,心跳请求处理接口
     */
    @PostMapping(value = "/deviceHeartBeat/{id}")
    public String deviceHeartBeat(@PathVariable("id") Integer id) {
        // 检查设备组是否存在于缓存中
        if (!redisCache.hasKey(CacheConstants.DEVICE_GROUP_KEY + id)) {
            // 设备组不存在,返回心跳失败
            return "Device group not found!";
        } else {
            // 更新设备组的心跳时间
            redisCache.expire(CacheConstants.DEVICE_GROUP_KEY + id, 10, TimeUnit.SECONDS);
            // 返回心跳成功
            return "Heartbeat successfully!";
        }
    }

如果用户异常退出设备组,你可以在后端实现一个定时任务,定时检查缓存中的设备组是否过期,如果过期则删除该设备组。代码示例如下:

	/**
	 * 定时任务:删除过期的设备组,每隔10秒检查一次缓存中的设备组是否超时
	 */
    @Scheduled(fixedDelay = 10000)
    public void checkDeviceGroupKey() {
        // 获取当前时间
        Date now = new Date();
  		Set<Object> deviceGroupKeys = redisCache.keys(CacheConstants.DEVICE_GROUP_KEY + "*");
        // 遍历缓存中的设备组DEVICE_GROUP_KEY,检查是否超时
        for (Object deviceGroupKey : deviceGroupKeys) {
            // 获取缓存中的设备组
            String key = (String) deviceGroupKey;
            // 如果缓存中的设备组存在
            if (redisCache.hasKey(key)) {
                // 获取缓存中的设备组的最后一次心跳时间
                Date lastHeartBeatTime = redisCache.getCacheObject(key);
                // 计算当前时间和最后一次心跳时间的差值
                long diff = now.getTime() - lastHeartBeatTime.getTime();
                // 如果差值大于10秒,说明设备组已经超时,将设备组从缓存中删除
                if (diff > 10000) {
                    redisCache.deleteObject(key);
                }
            }
        }
    }

也可以限制哪几个设备组需要被清除

    /**
     * 定时任务:删除过期的设备组,每隔10秒检查一次缓存中的设备组是否超时
     */
    @Scheduled(fixedDelay = 10000)
    public void checkDeviceGroupKey() {
        // 获取当前时间
        Date now = new Date();

        // 遍历缓存中的设备组DEVICE_GROUP_KEY,检查是否超时
        for (int i = 1; i <= 16; i++) {
            // 获取缓存中的设备组
            String key = CacheConstants.DEVICE_GROUP_KEY + i;
            // 如果缓存中的设备组存在
            if (redisCache.hasKey(key)) {
                // 获取缓存中的设备组的最后一次心跳时间
                Date lastHeartBeatTime = redisCache.getCacheObject(key);
                // 计算当前时间和最后一次心跳时间的差值
                long diff = now.getTime() - lastHeartBeatTime.getTime();
                // 如果差值大于10秒,说明设备组已经超时,将设备组从缓存中删除
                if (diff > 10000) {
                    redisCache.deleteObject(key);
                }
            }
        }
    }

后端缓存时间设置为10秒钟,前端每隔5秒向后端发送请求,那么在正常情况下,如果前端正常关闭,后端会在10秒钟后自动清除该设备组的缓存。

如果前端异常关闭,那么后端会在10秒钟后检测到该设备组的心跳信号已经停止,然后自动清除该设备组的缓存。

因此,这种方法可以保证在大多数情况下能够及时清除缓存,但是仍然可能存在一些极端情况导致缓存无法及时清除,比如网络故障等。文章来源地址https://www.toymoban.com/news/detail-728666.html

到了这里,关于如何实现设备组缓存的正确清除?——基于心跳请求和心跳响应的解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • npm、yarn、pnpm如何清除缓存?

    前端工程化创建项目会经常使用各种安装包管理工具,安装各种前端依赖包。例如,npm、yarn、pnpm等。时间一长,各种安装包管理工具的在安装依赖时,留下的缓存文件就会变得很大,以至于影响系统的运行,因此必要时清除缓存就是一个不错的选择。本文将着重介绍npm、y

    2024年02月07日
    浏览(61)
  • Linux服务器如何清除dns缓存

    DNS缓存是一个临时数据库,用于存储已解释的DNS查询信息。换句话说,每当你访问网站时,你的操作系统和网络浏览器都会保留域名和相应IP地址的记录。 这消除对远程DNS服务器重复查询,并允许你的操作系统或浏览器快速解析网站的域名。 但是在某些情况下,例如对网络问

    2023年04月15日
    浏览(40)
  • uniapp实现清除缓存

    一、页面加载时计算缓存大小(H5不支持) 二、点击清除缓存按钮调用清理缓存方法 三、清理缓存(并重新计算缓存大小)

    2024年01月21日
    浏览(32)
  • 前端部署发布项目后,如何通知用户刷新页面、清除缓存

    以下只是一些思路,有更好的实现方式可以留言一起交流学习 方式一:纯前端 在每次发布前端时,使用webpack构建命令生成一个json文件,json中写个随机生成的一个字符串(比如时间戳),每次打包程序都会自动更新这个json文件。 在项目中,通过定时任务或者在切换页面路由

    2024年02月05日
    浏览(55)
  • 如何有效清理您的Python环境:清除Pip缓存

    Python是一个广泛使用的高级编程语言,以其强大的库和框架而闻名。然而,随着时间的推移和不断安装新的包,Python环境可能会变得混乱不堪,尤其是pip缓存可能占用大量的磁盘空间。本文将向您展示如何有效地清理pip缓存,保持您的Python环境整洁。 为什么要清理Pip缓存?

    2024年01月20日
    浏览(63)
  • Chrome Edge Firefox Safari 如何清除 DNS 缓存

    Chrome Edge Firefox Safari 如何清除 DNS 缓存 如何清除浏览器的 DNS 缓存 (Chrome, Firefox, Safari) Chrome Chromium Edge Firefox Safari clear DNS Cache, flush DNS cache 请访问原文链接:https://sysin.org/blog/clear-browser-dns-cache/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 天下只剩三种(主

    2024年02月11日
    浏览(49)
  • 如何清除谷歌浏览器的缓存?这里有详细步骤

    如果你想解决加载或格式化问题,以改善你在谷歌Chrome上的浏览体验,那么清除缓存和cookie是一个很好的开始。以下是删除它们的方式和操作。 当你访问一个网站时,它有时会保存(或记住)某些信息。Cookie保存用户的浏览数据(征得他们的同意),缓存通过记住上次访问时

    2024年02月19日
    浏览(38)
  • 如何清除 Pip 缓存?从而优化 Python 环境并释放磁盘空间

    在 Python 开发中,Pip 是最常用的包管理工具之一,它用于安装、升级和管理 Python 包。然而,随着时间的推移,Pip 可能会积累大量的缓存文件,占用磁盘空间并可能导致一些问题。因此,定期清除 Pip 缓存是一个好习惯。本文将详细介绍如何清除 Pip 缓存,帮助您优化 Python 环

    2024年02月11日
    浏览(44)
  • 如何清除浏览器的 DNS 缓存 (Chrome, Firefox, Safari)

    如何清除浏览器的 DNS 缓存 (Chrome, Firefox, Safari) Chrome Chromium Edge Firefox Safari clear DNS Cache, flush DNS cache 请访问原文链接:https://sysin.org/blog/clear-browser-dns-cache/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 天下只剩三种(主流)浏览器: Apple Safari Mozilla Firefox

    2024年02月11日
    浏览(49)
  • 什么是心跳功能,心跳功能如何实现

    心跳功能的意思是指 DTU每隔一定时间,发一个数据包到数据中心 。  主要功能:    1.防止掉线 ,因为现在网络运营商为了防止一些终端挂在网上,而不传数据(因为GPRS或CDMA都是按流量收费的,当然也有包月的,你必须得先开通才能包月),所以当发现终端一定时间内没有

    2024年02月13日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包