当前位置: 首页 > news >正文

【 Redis | 实战篇 扩展 】

目录

前言:

1.达人探店功能

1.1.点赞功能

1.2.排行榜

2.关注

2.1.共同关注

2.2.关注推送

3.附近商铺

3.1.GEO基本用法

3.2.获取附近商铺

4.签到

4.1.BitMap

4.2.实现签到

4.3.统计连续签到

5.UV统计


前言:

实现达人探店,好友关注,附件商铺,用户签到,UV统计

1.达人探店功能

1.1.点赞功能

分析:实现点赞功能,那么一个用户是不是只能点赞一次,如果能进行多次点赞(这不刷起来了吗)

思路:一个用户只能点赞一次,点亮了,赞图标就高亮显示,再次点亮就是取消点赞

实现方案:

  • 数据库:数据库中创建一张表,每次用户点赞时,先访问数据库,数据库有对应数据,代表已经点赞,因此实现取消点赞功能(删除数据库对应数据),没有数据,则代表没有点赞,添加对应数据到数据库中
  • Redis:一人一赞,那么我们使用set集合(不可重复性),key为发笔记人的id,value为点赞用户id
  • 同时采用数据库和Redis:Redis做缓存实现快速查询,数据库做数据持久化

优化:由于前端需要后端返回一个布尔值,来判断是否点赞(是否显示高亮),而老师采用的是每次查询操作是先查询数据再判断是否点赞,但是由于我们笔记实体类中已经有了这个属性(布尔),我们可以直接在调用点赞业务代码时(你都在这设置了是否点赞了,那你直接将值赋值给属性即可)

问题:如果我们使用老师的方案,在每次查询业务时都需要查询数据库,根据登录用户id查,如果用户没有登录呢?你的查询操作就进行不下去了(要判断id是否为空),没有登录的用户连界面都访问不了

    @Overridepublic Result likeBlog(Long id) {//设置Redis的keyString key = RedisConstants.BLOG_LIKED_KEY + id;//查询RedisLong userId = UserHolder.getUser().getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());//判断是否存在if (score != null) {//Redis中已经存在//更新数据库boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();if (isSuccess) {//数据库更新成功后,才能删除RedisstringRedisTemplate.opsForZSet().remove(key, userId.toString());}} else {//不存在//更新数据库boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();if (isSuccess) {//数据库更新成功后,才能更新RedisstringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());}}Blog blog = getById(id);blog.setIsLike(score == null);return Result.ok();}

1.2.排行榜

分析:由于我们是要对点赞时间用户的排序(统计前五名先点赞的用户),因为是点赞用户肯定不止一个,因此我们需要使用集合的方式,并且是一个查询操作,可以采取Redis

集合分析:

set集合:由于我们是要统计排名,需要对数据进行排序,而set集合是无序的(不能使用

-------

list集合:一个用户只能点赞一次,那么就代表数据不能重复对吧,list集合是按照添加顺序来排序,但是它的原理是基于链表(可以重复),并且由于是链表代表它的查询速度慢(索引查询,首尾查),如果有大量数据需要查询,等待时间太长了

-------

sortedset集合:该集合不允许重复(保证唯一性),并且它可以根据你给定的score(分数)进行排序(默认从小到大)

思路:使用sortedset集合,我们需要统计前五名点赞的用户,是不是就是统计先点赞的用户,那么在用户点赞时会调用点赞业务,我们在业务中将原先的使用的存入Redis采用的set集合代码转变成sortedset集合代码即可(我们的score可以设置为时间戳,直接根据时间戳来排序)

查询排行榜:

Redis查询数据

==》判断数据是否存在

==》不存在(没人点赞),直接返回空

----

==》存在

==》将数据过滤,留下用户id

==》根据用户id查询数据库

==》将数据再次转变成前端要的数据

==》返回数据

 @Overridepublic Result queryLikes(Long id) {//查询RedisString key = RedisConstants.BLOG_LIKED_KEY + id;Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);//判断是否存在if (top5 == null || top5.isEmpty()){return Result.ok();}//转换格式List<Long> ids = top5.stream().map(Long::valueOf).toList();//根据ids查询List<UserDTO> userDTOS = userService.listByIds(ids).stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).toList();String join = StrUtil.join(",", ids);return Result.ok(userDTOS);}

问题:虽然我们从Redis中取出的数据是按照时间顺序排序的,但是由于我们使用的是mp的list查询方式,它会默认根据id的顺序查询(从小到大),并不会按照我们指定的顺序查询,最终我们查询出来的数据依然是排序错误(数据库原理:in()查询默认使用id正序查询)

解决:不使用这个查询方式,自己写sql语句即可

    @Overridepublic Result queryLikes(Long id) {//查询RedisString key = RedisConstants.BLOG_LIKED_KEY + id;Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);//判断是否存在if (top5 == null || top5.isEmpty()){return Result.ok();}//转换格式List<Long> ids = top5.stream().map(Long::valueOf).toList();//根据ids查询String join = StrUtil.join(",", ids);List<UserDTO> userDTOS = userService.query().in("id", ids).last("ORDER BY FIELD(id," + join + ")").list().stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).toList();return Result.ok(userDTOS);}

解释:因为我们设置score时设置的是每次点赞的时间戳,因此我们可以直接根据时间戳来查询排行榜(默认正序),所以我们只需要根据索引查询5个就行(索引默认从0开始:0到4即可)

2.关注

2.1.共同关注

分析:共同关注代表的是不是就是两个人关注的交集,并且我们依然是查询判断操作,使用Redis,使用哪个数据结构呢?求交集,使用set集合

    @Overridepublic Result followCommon(Long followId) {//1.获取用户idLong userId = UserHolder.getUser().getId();//2.设置keyString key1 = "follows:" + userId;String key2 = "follows:" + followId;//3.Redis中查询交集Set<String> set = stringRedisTemplate.opsForSet().intersect(key1, key2);//4.转换格式if (set == null || set.isEmpty()){return Result.ok(Collections.emptyList());}List<Long> ids = set.stream().map(Long::valueOf).toList();//5.查询数据库List<UserDTO> userDTOS = userService.listByIds(ids).stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).toList();return Result.ok(userDTOS);}

2.2.关注推送

介绍:关注推送也叫Feed流(投喂),通过无限下拉刷新数据,获取信息(刷视频)

模式:

  • 传统模式:用户需要自己去寻找信息,自己鉴别这个信息是不是自己想要的(用户寻找内容)
  • Feed流:自动根据用户的行为来匹配数据,直接推送你想要的数据(大数据)(刷视频根据你的停留时间来给你推送该类型的视频)(内容匹配用户)

Feed流的模式:

Timeline:不做内容筛选,简单的按照内容发布时间排序,常用于好友或关注。例如朋友圈
优点:信息全面,不会有缺失。并且实现也相对简单
缺点:信息噪音较多,用户不一定感兴趣,内容获取效率低

智能排序:利用智能算法屏蔽掉违规的、用户不感兴趣的内容。推送用户感兴趣信息来吸引用户
优点:投喂用户感兴趣信息,用户粘度很高,容易沉迷
缺点:如果算法不精准,可能起到反作用

总结:由于我们是个人空间的笔记展示,使用第一种即可 

 Feed流的实现方案:

  • 拉模式(读扩散)
  • 推模式(写扩散)
  • 推拉结合

拉模式:

介绍:只有当用户读这篇笔记时才会加载(发件箱--收件箱)

例子:每个发信的用户(作者)都有对应的发件箱(存储笔记的空间),当张三发布了一篇笔记,李四发布了两篇笔记,他们各自的笔记会发送到自己的发件箱中(并且按照时间戳排序(互通,共享)从小到大不会重复),而王五关注了张三,但是王五平时不会访问张三,所以王五的收件箱是空的,只有当王五去访问这篇笔记时(收件箱才会加载),才会拉取张三的消息(笔记)(一个个拉),拉取完成后会进行时间排序(从小到大)

  • 优点:节省内存空间(因为一般是空的)
  • 缺点:每次都需要重新拉取并且进行排序(耗时长,延迟长)

总结:拉模式(只有当你读的时候才会加载)(读扩散)

拉模式:

介绍:用户发了消息直接就传递到收件箱中(写扩散)

例子:没有发件箱了,只有收件箱,当张三发送消息,会直接将消息推送到他的所以粉丝的收件箱中,然后进行排序

  • 优点:延迟低
  • 缺点:有多少粉丝就需要发送多少份(内存占用高)

推拉结合:
介绍:读写混合

例子:有两个作者,一个作者张三是一个拥有千万粉丝的大V博主,另一个作者李四是一个粉丝量少的普通博主,当李四发消息时,采用推模式(粉丝少,直接发),大V发消息时,根据粉丝的活跃度做处理,由于活跃的粉丝相较于是少的,那么活跃的粉丝采用推模式,普通粉丝采用拉模式(不经常访问)

  • 优点:节省内存空间,延迟低
  • 缺点:实现复杂

分析:由于我们用户少,所以采用推模式,我们要展示的是笔记,肯定是先展示最新发布的笔记,然后依次展示,所以我们需要进行根据发布时间进行排序,我们还是进行查找操作,依然选择Redis来进行缓存,使用哪个集合呢?感觉list和sortedset都可以

思考:我们使用的是Feed流,我们的数据是不是在不断更新,因此索引也一直在变化(首尾一样),而List不支持流动处理,因此排除,并且由于我们数据不断变化的,我们能才用线性分页查询吗?

例子:如果采用线性查询,每次查询五条数据,第一次查询完后,更新了两条数据(按时间发布排序,他们会挤掉先前的第一第二),所以当我们第二次查询时会查询到重复的数据

实现:使用滚动分页查询,每次记录查询的最后一个数据的score值即可,下次就从这查询(要保证有序)

问题:那么第一次查询呢?我们没有记录数据啊

解决:由于我们是按从大到小排序,我们直接使用一个无限大的值即可,并且我们不能使用sortedset的按排名查(排名会变),只能使用范围查询(score值不变)

细节:如果我们记录查询的最后一个数据的score值时,它有重复值(多个),那么你怎么知道你是从哪个查询,因此我们需要记录最后一个值的重复值有几个(跳过即可)

@Overridepublic Result queryBlogFollow(Long max, Integer offset) {//1.获取用户idLong userId = UserHolder.getUser().getId();//2.根据id获取Redis中的数据String key = "feed:" + userId;Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0F, max, offset, 3);//3.判断是否为空if (typedTuples == null || typedTuples.isEmpty()){return Result.ok();}//4.获取查询博客的idList<Long> ids = new ArrayList<>(typedTuples.size());//5.设置时间初始值int os = 1;long minTime = 0;for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {ids.add(Long.valueOf(typedTuple.getValue()));long time = typedTuple.getScore().longValue();if(time == minTime){os++;}else {minTime = time;os = 1;}}//6.查询数据库String join = StrUtil.join(",", ids);List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + join + ")").list();BlogData blogData = new BlogData();blogData.setList(blogs);blogData.setOffset(os);blogData.setMinTime(minTime);return Result.ok(blogData);}

3.附近商铺

3.1.GEO基本用法

GEO就是Geolocation的简写形式,代表地理坐标。Redis在3.2版本中加入了对GEO的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据。

常见的命令有:

  • GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member)
  • GEODIST:计算指定的两个点之间的距离并返回
  • GEOHASH:将指定member的坐标转为hash字符串形式并返回
  • GEOPOS:返回指定member的坐标
  • GEORADIUS:指定圆心、半径,找到该圆内包含的所有member,并按照与圆心之间的距离排序后返回。6.2以后已废弃
  • GEOSEARCH:在指定范围内搜索member,并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。6.2.新功能
  • GEOSEARCHSTORE:与GEOSEARCH功能一致,不过可以把结果存储到一个指定的key

3.2.获取附近商铺

分析:还是查询,使用Redis

注意:由于我们用户可以选择不同的分类来进行查询店铺,不一定就是距离查询,因此我们需要判断

 @Overridepublic Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {//1.判断是否是距离查询if (x == null || y == null) {// 根据类型分页查询Page<Shop> page = query().eq("type_id", typeId).page(new Page<>(current, SystemConstants.DEFAULT_PAGE_SIZE));// 返回数据return Result.ok(page.getRecords());}//2.是距离查询int from = (current - 1) * SystemConstants.DEFAULT_PAGE_SIZE;int end = current * SystemConstants.DEFAULT_PAGE_SIZE;//3.查询Redis,按照距离排序,分页String key = RedisConstants.SHOP_GEO_KEY + typeId;GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo().search(key,GeoReference.fromCoordinate(x, y),new Distance(5000),RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance().limit(end));//4.解析出idif (results == null) {return Result.ok(Collections.emptyList());}List<GeoResult<RedisGeoCommands.GeoLocation<String>>> list = results.getContent();//4.1截取from - endif (list.size() <= from) {return Result.ok(Collections.emptyList());}List<Long> ids = new ArrayList<>(list.size());Map<String,Distance> distanceMap = new HashMap<>(list.size());list.stream().skip(from).forEach(result -> {//4.2.获取店铺idString shopIdStr = result.getContent().getName();ids.add(Long.valueOf(shopIdStr));//4.3.获取距离Distance distance = result.getDistance();distanceMap.put(shopIdStr,distance);});//5.根据id查询店铺信息String idsStr = StrUtil.join(",", ids);List<Shop> shops = query().in("id", ids).last("ORDER BY FIELD(id," + idsStr + ")").list();for (Shop shop : shops) {shop.setDistance(distanceMap.get(shop.getId().toString()).getValue());}return Result.ok(shops);}

4.签到

4.1.BitMap

分析:如果我们使用数据库将每天用户签到的数据一一记录下来,那么我们将要存储大量数据,成本大,因此我们需要使用一个简单的方式来实现签到记录数据的实现

简单方法:签到只有两个选择:签到还是没有签到,我们二进制是不是只有0和1,那么我们可以使用1代表签到的,0代表未签到的,怎么统计每一月,每一年的数据呢,使用Redis key为时间前缀,value为签到值

实现:一般是统计一个月的签到情况,因此我们key前缀具体到月,value的二进制位数为32位即可,因为类型简单,使用Redis的String类型(BitMap)即可

BitMap用法

介绍:Redis中是利用string类型数据结构实现BitMap,因此最大上限是512M,转换为bit则是2A32个bit位。
BitMap的操作命令有:

  • SETBIT:向指定位置(offset)存入一个0或1
  • GETBIT:获取指定位置(offset)的bit值
  • BITCOUNT:统计BitMap中值为1的bit位的数量
  • BITFIELD:操作(查询、修改、自增)BitMap中bit数组中的指定位置(offset)的值
  • BITFIELD_RQ:获取BitMap中bit数组,并以十进制形式返回
  • BITOP:将多个BitMap的结果做位运算(与、或、异或)
  • BITPOS:查找bit数组中指定范围内第一个0或1出现的位置

4.2.实现签到

@Overridepublic Result sign() {//1.获取用户idLong userId = UserHolder.getUser().getId();//2.获取当前时间LocalDateTime now = LocalDateTime.now();//3.设置时间String keyStrTime = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = USER_SIGN_KEY + userId + keyStrTime;//4.获取天数int dayOfMonth = now.getDayOfMonth();//5.写入RedisstringRedisTemplate.opsForValue().setBit(key,dayOfMonth-1,true);return Result.ok();}

4.3.统计连续签到

@Overridepublic Result signCount() {//1.获取用户idLong userId = UserHolder.getUser().getId();//2.获取当前时间LocalDateTime now = LocalDateTime.now();//3.设置时间String keyStrTime = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = USER_SIGN_KEY + userId + keyStrTime;//4.获取天数int dayOfMonth = now.getDayOfMonth();//5.查询Redis,查询本月数据List<Long> list = stringRedisTemplate.opsForValue().bitField(key,BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));if(list == null || list.isEmpty()){return Result.ok(0);}Long aLong = list.get(0);if(aLong == null || aLong == 0){return Result.ok(0);}//6.循环遍历int count = 0;while(true){//做与运算if((aLong & 1) == 0){//跳出循环break;}else {//计数器加一count++;}//向右移动一位aLong >>>= 1;}return Result.ok(count);}

5.UV统计

UV:全称Unique Visitor,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站,只记录1次。
PV:全称Page View,也叫页面访问量或点击量,用户每访问网站的一个页面,记录1次PV,用户多次打开页面,则记录多次PV。往往用来衡量网站的流量。

分析:UV统计在服务端·实现很困难,因为要判断该用户是否已经统计过了,那么就需要查询数据,因此我们的已经访问的用户信息都需要保存到Redis中,如果用户量大,需要考虑内存

解决:

相关文章:

【 Redis | 实战篇 扩展 】

目录 前言&#xff1a; 1.达人探店功能 1.1.点赞功能 1.2.排行榜 2.关注 2.1.共同关注 2.2.关注推送 3.附近商铺 3.1.GEO基本用法 3.2.获取附近商铺 4.签到 4.1.BitMap 4.2.实现签到 4.3.统计连续签到 5.UV统计 前言&#xff1a; 实现达人探店&#xff0c;好友…...

【HarmonyOS Next之旅】DevEco Studio使用指南(二十五) -> 端云一体化开发 -> 业务介绍(二)

目录 1 -> 工作原理 2 -> 约束与限制 2.1 -> 支持的设备 2.2 -> 支持的国家/地区 2.3 -> 支持的签名方式 3 -> 总结 3.1 -> 关键功能与工具 3.2 -> 开发流程 3.3 -> 典型场景与优化 3.4 -> 常见问题与解决 3.5 -> 总结 1 -> 工…...

空调系统虚拟标定技术:新能源汽车能效优化的革命性突破

title: 空调系统虚拟标定技术&#xff1a;新能源汽车能效优化的革命性突破 date: 2025-05-15 categories: 新能源汽车技术 tags: [空调系统, 虚拟标定, PID控制, 数字孪生, 能效优化] description: 本文深度解析空调系统虚拟标定技术在新能源汽车中的应用&#xff0c;揭秘如何…...

MCP Server开发并使用自定义天气查询工具查询城市天气

1.本地安装node.js环境 2.本地创建mcp文件夹&#xff0c;搭建mcp环境 在文件夹下cmd执行npm init -y初始化npm项目 3.创建weather-server.js文件&#xff0c;代码如下 // weather-server.js import { McpServer } from "modelcontextprotocol/sdk/server/mcp.js"…...

virtualbox选项“启用套嵌vt-x/amd-v“不可用

“启用套嵌vt-x/amd-v”选项不可用。 解决方法&#xff1a; 切换到virtualbox安装目录&#xff0c;执行如下命令查看虚拟机名称&#xff1a; .\VBoxManage.exe list vms比如返回: winxp 执行如下命令开启64位&#xff0c;注意把"winxp"换成你的虚拟机名字&#x…...

windows powershell 判断 进程号是否存在

在 Windows PowerShell 中&#xff0c;你可以使用多种方法来检查一个特定的进程号&#xff08;PID&#xff09;是否存在。以下是几种常用的方法&#xff1a; 方法1&#xff1a;使用 Get-Process 命令 你可以尝试获取具有特定 PID 的进程。如果该进程存在&#xff0c;Get-Proce…...

JAVA SE 多线程(下)

文章目录 &#x1f4d5;1. 常见的锁策略✏️1.1 乐观锁VS悲观锁✏️1.2 轻量级锁VS重量级锁✏️1.3 自旋锁✏️1.4 公平锁VS非公平锁✏️1.5 可重入锁和不可重入锁✏️1.6 读写锁 &#x1f4d5;2. 死锁✏️2.1 哲学家就餐问题✏️2.2 形成死锁的必要条件✏️2.3 如何避免死锁 &…...

DeepSeek+Dify之九多模态大模型识别图片

Dify之八添加各种在线大模型 文章目录 背景整体流程测试数据用到的节点开始列表操作LLM结束实现步骤1、新建工作流2、开始节点3、列表操作4、LLM节点(多模态大模型检索)5、结束节点测试发布导出背景 有了上一篇文章的基础,现在可以了解下多模态大模型识别图片的工作流 整体…...

软件工程(七):MQTT协议

概念 特性描述协议类型应用层协议&#xff08;基于 TCP/IP&#xff09;通信模式发布/订阅&#xff08;Publish/Subscribe&#xff09;网络开销小报文头仅 2 字节起&#xff0c;非常轻量保持长连接使用 Keep Alive 机制&#xff0c;适合持续连接的设备面向物联网广泛用于智能家…...

网络 :网络基础【网络框架认识】

网络 &#xff1a;网络基础【对网络的认识】 &#xff08;一&#xff09;网络发展&#xff08;二&#xff09;协议1、协议是什么&#xff1f;2、协议分层3、OSI七层模型4、TCP/IP五层(或四层)模型5、系统与网络的关系6、总结 &#xff08;三&#xff09;网络传输流程1、网络传输…...

Kotlin 极简小抄 P8(不可空类型、可空类型、注意事项、非空断言 !!)

Kotlin 概述 Kotlin 由 JetBrains 开发&#xff0c;是一种在 JVM&#xff08;Java 虚拟机&#xff09;上运行的静态类型编程语言 Kotlin 旨在提高开发者的编码效率和安全性&#xff0c;同时保持与 Java 的高度互操作性 Kotlin 是 Android 应用开发的首选语言&#xff0c;也可…...

几种超声波芯片的特点和对比

一 CX20106A ZIP - 8 CX20106A ZIP - 8 的核心竞争力在于高性价比、易用性和抗光干扰能力&#xff0c;尤其适合消费电子、短距离工业检测和低成本物联网场景。尽管在距离和精度上不及高端芯片&#xff0c;但其成熟的电路方案和广泛的市场应用&#xff08;如经典红外遥控升级为超…...

软考 系统架构设计师系列知识点之杂项集萃(66)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;65&#xff09; 第106题 一般说来&#xff0c;SoC称为系统级芯片&#xff0c;也称片上系统&#xff0c;它是一个有专用目标的集成电路产品。以下关于SoC不正确的说法是&#xff08;&#xff09;。…...

Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]]

Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]] 目录 Linux云计算训练营笔记day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]]1.find练习2.vim高级使用2.1 命令模式:2.2 插入模式:2.3 末行模式: 3. vimdiff4. ping5.…...

年会招标抽奖活动软件———仙盟创梦IDE

年会是企业一年的总结与欢庆时刻&#xff0c;而抽奖环节更是点燃全场气氛的关键。如何让抽奖环节既大气又充满仪式感&#xff1f;选对抽奖软件至关重要&#xff01;本文精心挑选了 3 款兼具实用性与氛围感的年会抽奖软件&#xff0c;从界面设计到功能特色&#xff0c;全方位为你…...

智防火灾,慧控能耗:物联网赋能金融行业电气安全革新

摘要 随着金融行业对电气安全需求的不断提升&#xff0c;传统用电管理模式已难以满足现代金融机构对火灾防控、能耗管理和智能运维的要求。本文基于物联网、云计算及大数据分析技术&#xff0c;提出一套针对金融行业的安全用电解决方案。该方案通过智能化硬件部署与平台化管理…...

UML基本概念:构造块、公共机制与规则

本篇来介绍UML的一些基础概念。 1 UML的结构 2 构造块 UML构造块是构成UML模型的基础元素&#xff0c;它们共同构成了UML的核心。 UML 的三种基本构造块是&#xff1a; 事物&#xff1a;对模型中重要元素的抽象&#xff0c;如类、对象等等关系&#xff1a;用来连接事物的&a…...

JAVA项目中常见的注解总结

以下是 Spring Boot/Spring MVC 项目中按使用频率排序的核心注解总结&#xff0c;包含常用场景和示例&#xff0c;帮助你快速掌握高频开发需求&#xff1a; 一、高频基础注解&#xff08;框架核心&#xff09; 1. SpringBootApplication&#xff08;启动类注解&#xff09; …...

数字电子技术基础(六十二)——使用Multisim软件绘制边沿触发的D触发器和JK触发器

1 使用Mulitism软件模拟时钟触发的D触发器 D触发器是一种基本的数字电路存储元件&#xff0c;它在时钟信号的边沿将输入数据D传递到输出Q。下面开始使用Multisim软件来模拟时钟触发的D触发器。 器件选择&#xff1a; 触发器选择&#xff1a;在组选项栏中点击Misc Digital&am…...

滚珠丝杆的承载力是多少?

滚珠丝杆的承载力不是一个固定值&#xff0c;它受到多种因素的影响&#xff0c;包括直径、螺距、滚珠个数、滚珠直径、材料、润滑条件等。 ‌滚珠丝杆的承载力主要取决于其额定动负荷和静负荷&#xff0c;额定动负荷是指在特定条件下&#xff0c;滚珠丝杆能够承受的动态负载&am…...

CQF预备知识:一、微积分简介 —— 基本术语详解

文中内容仅限技术学习与代码实践参考&#xff0c;市场存在不确定性&#xff0c;技术分析需谨慎验证&#xff0c;不构成任何投资建议。 &#x1f4d6; 数学入门全解 本教程为复习课程&#xff0c;旨在帮助读者复习数学知识。教程涵盖以下四个主题&#xff1a; 微积分线性代数微…...

【深度估计 Depth Estimation】数据集介绍

文章目录 总览1. KITTI Depth Completion1.1. 来源1.2. 采集场景1.3. 数据集内容1.4. 标注内容1.5. 任务目标1.6. 样本量1.7. 下载链接 2. KITTI Stereo Evaluation 20152.1. 来源2.2. 采集场景2.3. 数据集内容2.4. 标注内容2.5. 任务目标2.6. 样本量2.7. 下载链接 3. Virtual …...

鸿蒙UI开发——Builder与LocalBuilder对比

1、概 述 在ArkUI中&#xff0c;有的朋友应该接触过Builder和LocalBuilder。其中有了LocalBuilder的存在&#xff0c;是为了解决组件的父子关系和状态管理的父子关系保持一致的问题。 这里面最直观的表现则是this的指向问题与组件刷新问题&#xff0c;本文对Builder与LocalBu…...

FFT加窗和抽取滤波

FFT加窗 在信号处理中&#xff0c;为了减少频谱泄漏&#xff08;Spectral Leakage&#xff09;&#xff0c;在进行快速傅里叶变换&#xff08;FFT&#xff09;时通常会采用加窗&#xff08;Windowing&#xff09;技术。包括常见的窗函数及其特性对比。 MATLAB FFT 加窗流程 采…...

CentOS 10:启动telnet服务

参考&#xff0c; 鳥哥私房菜 - 第七章、網路安全與主機基本防護&#xff1a;限制埠口, 網路升級與 SELinux 7.3.3 埠口与服务的启动/关闭及开机时状态设定 我们知道系统的 Telnet 服务通常是以 super daemon 来控管的&#xff0c;请您启动您系统的 telnet 试看看。 1 要启动 …...

腾讯位置服务重构出行行业的技术底层逻辑

位置智能&#xff1a;重构出行行业的技术底层逻辑 在智慧城市建设与交通出行需求爆发的双重驱动下&#xff0c;位置服务正从工具层跃升为出行行业的核心基础设施。腾讯位置服务以“连接物理世界与数字空间”为核心理念&#xff0c;通过构建高精度定位、实时数据融合、智能决策…...

webpack5所用依赖以及对应的版本

所有依赖以及版本 {"name": "market-web","version": "0.1.0","private": true,"scripts": {"dev": "cross-env NODE_ENVdevelopment webpack serve --config ./vue.config.js","buil…...

vue-cli 构建打包优化(JeecgBoot-Vue2 配置优化篇)

项目&#xff1a;jeecgboot-Vue2 在项目二次开发后&#xff0c;在本人电脑打包时间为3分35秒左右 webpack5默认优化&#xff1a; Tree Shaking&#xff08;摇树优化&#xff09;&#xff1a;删除未使用的代码base64 内联&#xff1a; 小于 8KB 的资源&#xff08;图片等&…...

Webpack 分包策略详解及实现

Webpack 的分包策略&#xff08;Code Splitting&#xff09;是优化前端应用性能的重要手段&#xff0c;它能将代码拆分成多个 bundle&#xff0c;实现按需加载或并行加载&#xff0c;从而减少初始加载时间。 分包策略的必要性 在大型项目中&#xff0c;如果将所有代码打包到一…...

大模型微调与高效训练

随着预训练大模型&#xff08;如BERT、GPT、ViT、LLaMA、CLIP等&#xff09;的崛起&#xff0c;人工智能进入了一个新的范式&#xff1a;预训练-微调&#xff08;Pre-train, Fine-tune&#xff09;。这些大模型在海量数据上学习到了通用的、强大的表示能力和世界知识。然而&…...

postgreSQL日常维护

目录 登录数据库 数据库操作列出列出库 创建库 删除库 切换库 查看库的大小 数据表操作 列出表 创建表 复制表 删除表 查看表的结构 模式操作命令 创建模式 默认模式 删除模式 查看所有模式 在指定模式中创建表 切换当前模式 查看当前所在schema 查看搜索…...

数据直观分析与可视化

数据直观分析与可视化 一、数据的直观分析核心价值 数据的直观分析旨在通过视觉化的方式&#xff0c;帮助人们更直观、更快速地理解数据的特征和模式&#xff0c;从而发现趋势、异常值、分布情况以及变量之间的关系&#xff0c;为决策提供支持。 数据可视化与信息图形、信息可…...

BeamDojo: Learning Agile Humanoid Locomotion on Sparse Footholds

BeamDojo: Learning Agile Humanoid Locomotion on Sparse Footholds 研究动机解决方案技术路线踏脚点奖励双Critic进行稀疏奖励学习两阶段学习地形感知运动马尔可夫决策空间Sim2Real 附录实验结果 BeamDojo: Learning Agile Humanoid Locomotion on Sparse Footholds 研究动机…...

Spark大数据分与实践笔记(第五章 HBase分布式数据库-02)

文章目录 每日一句正能量第五章 HBase分布式数据库章节概要5.2 HBase的集群部署 每日一句正能量 人有三样东西是无法隐瞒的&#xff0c;咳嗽&#xff0c;穷困和爱&#xff0c;你想隐瞒越欲盖弥彰。人有三样东西是不该挥霍的&#xff0c;身体&#xff0c;金钱和爱&#xff0c;你…...

【面经分享】微派网络一面

HashMap 如何解决 哈希冲突&#xff1f; HashMap 是拉链法解决。 发生哈希冲突时&#xff0c;同一个槽位上&#xff0c;会形成一个链表。 一个槽位上的节点达到树化的阈值后&#xff0c;会树化为红黑树。 拉链法&#xff1a;哈希冲突时&#xff0c;同一个哈希槽拉成一个链表…...

【寻找Linux的奥秘】第七章:虚拟地址空间

前言 本专题将基于Linux操作系统来带领大家学习操作系统方面的知识以及学习使用Linux操作系统。上一章我们简单认识了环境变量&#xff0c;本章将讲解操作系统中另一个重要的概念——程序地址空间。 1. 初步认识 之前在我们学习C语言和C时我们知道&#xff0c;在我们的程序中不…...

网络安全-等级保护(等保) 2-0 等级保护制度现行技术标准

################################################################################ 第二章&#xff1a;现行等保标准要求&#xff0c;通过表格方式详细拆分了等保的相关要求。 GB 17859-1999 计算机信息系统 安全保护等级划分准则【现行】 GB/T22240-2020 《信息安全技术…...

Linux:进程信号---信号的保存与处理

文章目录 1. 信号的保存1.1 信号的状态管理 2. 信号的处理2.1 用户态与内核态2.2 信号处理和捕捉的内核原理2.3 sigaction函数 3. 可重入函数4. Volatile5. SIGCHLD信号 序&#xff1a;在上一章中&#xff0c;我们对信号的概念及其识别的底层原理有了一定认识&#xff0c;也知道…...

【Linux】C语言模拟实现shell命令行(程序替换原理)

目录 一、自动化构建工具&#xff08;makefile&#xff09; 二、输出提示符 三、获取用户输入的数据 四、将用户输入的指令字符串进行分割&#xff1a; 五、执行用户输入的命令 六、发现cd命令用不了&#xff08;内建命令&#xff09; 原因在于&#xff1a; 七、处理内…...

WordPress Madara插件存在文件包含漏洞(CVE-2025-4524)

免责声明 本文档所述漏洞详情及复现方法仅限用于合法授权的安全研究和学术教育用途。任何个人或组织不得利用本文内容从事未经许可的渗透测试、网络攻击或其他违法行为。使用者应确保其行为符合相关法律法规,并取得目标系统的明确授权。 对于因不当使用本文信息而造成的任何直…...

【Java】泛型在 Java 中是怎样实现的?

先说结论 , Java 的泛型是伪泛型 , 在运行期间不存在泛型的概念 , 泛型在 Java 中是 编译检查 运行强转 实现的 泛型是指 允许在定义类 , 接口和方法时使用的类型参数 , 使得代码可以在不指定具体类型的情况下操作不同的数据类型 , 从而实现类型安全的代码复用 的语言机制 . …...

Lambda表达式的高级用法

今天来分享下Java的Lambda表达式&#xff0c;以及它的高级用法。 使用它可以提高代码的简洁度&#xff0c;使代码更优雅。 一、什么是lambda表达式 Lambda 表达式是 Java 8 引入的特性&#xff0c;用于简化匿名内部类的语法&#xff0c;使代码更简洁&#xff0c;尤其在处理函…...

ctfhub技能书http协议

http://challenge-ffe8afcf1a75b867.sandbox.ctfhub.com:10800/index.php curl -v -X CTFHUB http://challenge-ffe8afcf1a75b867.sandbox.ctfhub.com:10800/index.php curl&#xff1a;用于发送 HTTP 请求的命令行工具。 -v&#xff08;--verbose&#xff09;&#xff1a;开启…...

面试题 - 微服务相关的经典问题(33道)

1.什么是微服务&#xff1f; 微服务&#xff08;Microservices&#xff09;是一种软件架构风格&#xff0c;将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能&#xff0c;并通过轻量级通信机制&#xff08;如HTTP&#xff09;相互协作…...

在C#中对List<T>实现多属性排序

本文介绍了四种实现多级排序的方法&#xff1a;1. LINQ链式调用&#xff1a;使用OrderBy和ThenBy实现多级排序&#xff0c;直观易读&#xff0c;适合动态需求&#xff0c;返回新列表。2. 自定义比较器&#xff08;IComparer&#xff09;&#xff1a;适用于复杂或高频排序&#…...

C++初阶-vector的模拟实现3

目录 1.预备知识&#xff1a;initializer_list 1.1初步了解 1.2关于initializer_list的deepseek的回答 C中的 std::initializer_list 主要特性 常见用途 1. 接受列表的构造函数和函数 2. 基于范围的 for 循环 重要注意事项 实现示例 2.vector::vector(initializer_li…...

详解鸿蒙仓颉开发语言中的日志打印问题

一门新的开发语言在诞生初期&#xff0c;由于它本身的特性和使用人数暂时较少&#xff0c;会容易出现一些大家不太容易理解的问题&#xff0c;或者说有一些坑。今天就详细分享一下仓颉开发语言中的日志打印相关内容&#xff0c;带大家踩一踩坑。 AppLog 在新创建的项目中&…...

dify基于文本模型实现微调Fine-tune语料构造工作流

主要是分为5个部分。分别是&#xff1a;开始、文档提取器、代码执行、LLM大语言模型、结束 5个部分 打开dify&#xff0c;创建一个空白页面-选择工作流&#xff0c;我们给应用起个名字。 创建完成后&#xff0c;进入工作流画布界面 开始 在开始节点中新建2个输入参数。1个是用…...

手机充电协议

1、手机快充 公有&#xff1a;PD、QC(高通骁龙芯片&#xff09; 私有&#xff1a; 华为&#xff1a;FCP&#xff08;fast charge protocol) 、SCP( super charge protocol) 、 小米&#xff1a; Mi Turbo Charge oppo&#xff1a;VOOC/SuperVOOC vivo&#xff1a;FlashCharge、…...

HarmonyOS 应用开发,如何引入 Golang 编译的第三方 SO 库

本指南基于笔者临时修复的 ohos_golang_go 项目fork&#xff0c;解决HO 应用导入 cgo编译产物时的 crash 问题。 1. 下载 ohos_golang_go git clone https://gitcode.com/deslord/ohos_golang_go.git&#x1f4cc; 该仓库为笔者临时修复版本&#xff0c;修复了 CGO 编译模式下…...