【Redis】zset 类型

zset

  • 一. zset 类型介绍
  • 二. zset 命令
    • zadd
    • zcard、zcount
    • zrange、zrevrange、zrangebyscore
    • zpopmax、zpopmin
    • zrank、zrevrank、zscore
    • zrem、zremrangebyrank、zremrangebyscore
    • zincrby
    • 阻塞版本命令:bzpopmax、bzpopmin
    • 集合间操作:zinterstore、zunionstore
  • 三. zset 命令小结
  • 四. zset 内部编码方式
  • 五. zset 使用场景
    • 排行榜系统

一. zset 类型介绍

  • zset (有序集合):相对于字符串、列表、哈希、集合来说会有一些陌生。它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有一个唯一的浮点类型的分数 (score) 与之关联,着使得有序集合中的元素是可以维护有序性的,但这个有序不是用下标作为排序依据而是用这个分数。

如下图所示,该有序集合显示了三国中的武将的武力。

在这里插入图片描述

  • 有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能,合理地利用有序集合,可以帮助我们在实际开发中解决很多问题。
  • 有序集合中的元素是不能重复的,但分数允许重复。类比于一次考试之后,每个人一定有一个唯一的分数,但分数允许相同
  • 排序规则:分数不同时按照分数进行排序,分数相同时按照字典序进行排序,实际上 zset 内部就是按照升序方式来进行排序的。

列表、集合、有序集合三者的异同点,如下:

数据结构是否允许重复元素是否有序有序依据应用场景
list索引下标时间轴、消息队列等
set标签、社交等
zset分数排行榜系统、社交等

注意:list 的有序指的是按照某种顺序,而 zset 的有序指的是升序/降序。

二. zset 命令

zadd

  • zadd:添加或者更新指定的元素以及关联的分数到 zset 中,分数应该符合 double 类型,+inf/-inf 作为正负极限也是合法的。
    • 添加的时候:既要添加元素,又要添加分数;member 和 score 称为一个 “pair”,不要把 member 和 score 理解成 “键值对” (key-value pair)
    • 键值对中存在明确的角色区分,谁是键谁是值是明确的,一定是根据键找对应的值。
    • 对于 zset 来说,既可以通过 member 找到对应的 score;又可以通过 score 找到匹配的 member;
  • 语法:zadd key [NX|XX] [CH] [INCR] score member [score member ...]
    • 不加 XX | NX:如果当前 member 不存在,此时就会达到添加新 member 的效果;如果当前 member 已经存在,此时就会达到更新 member 对应 score 的效果。
      • 加上 XX:仅仅用于更新已经存在的 member 对应 score 的效果,不会添加新 member
      • 加上 NX:仅仅用于添加 member 的效果,不会更新已经存在的 member 对应的 score
    • CH:默认情况下,zadd 返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数。
    • INCR:此时命令类似 zincrby 的效果,将元素的分数加上指定的分数。此时只能指定⼀个元素和分数。
  • 时间复杂度:O(logN),N 是有序集合中元素的个数。
    • 之前 hash、list、set 添加一个元素,都是 O(1)
    • 由于 zset 是有序结构,要求新增的元素放在合适的位置,之所以是 O(logN),就是充分利用了有序这样的特点 (zset 内部的数据结构主要是跳表)
  • 返回值:本次添加成功的元素个数。

在这里插入图片描述

Redis 内部存储数据的时候,是按照二进制的方式来存储的,这就意味着,Redis 服务器不负责 “字符编码” 的,要把二进制字节转回到汉字,还需要客户端来支持,登入 Redis 客户端时的命令 redis-cli --raw

在这里插入图片描述

如果修改的分数,影响到了之前的顺序,就会自动移动元素的位置,保持原有的升序顺序不变。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

zadd 在默认情况下,返回值就是新增成功的元素个数。若更新时不存在元素,则更新失败。

在这里插入图片描述

在这里插入图片描述

添加 incr 修改 member 的 score 时,后面只能跟一个 member,且返回值是 member 之后的 score

  • C++ 中 std::set 存储的元素 (key-value) 的 key 是有序的,但是这里的 key 是不能修改的。
  • Redis 中 zset 的 member 是可以修改的,修改之后 score 仍然要排序,满足有序。

zcard、zcount

  • zcard:获取⼀个 zset 的基数 (cardinality),即 zset 中的元素 member 的个数。
  • 语法:zcard key
  • 时间复杂度:O(1)
  • 返回值:zset 内的元素个数。

在这里插入图片描述

  • zcount:返回分数在 min 和 max 之间的元素个数,默认情况下,min 和 max 都是包含的。但是可以通过 ( 进行排除。
  • 语法:zcount key min max
  • 时间复杂度:O(logN)
    • 先根据 min 找到对应的元素,再根据 max 找到对应的元素,是 O(logN)
    • 如果区间中元素比较多,此时就需要进行遍历,时间复杂度:O(logN + M),N 是 zset 中元素的个数,M 是区间中元素的个数。
    • 实际 zset 内部,会记录每个元素当前 “排行”/“次序”,查询到元素,就直接知道了元素所在的 “次序” (下标),就可以直接把 max 对应的元素次序和 min 对应的元素次序,做差即可得出结果。
  • 返回值:满足条件的元素列表个数。

在这里插入图片描述

  • 使用 ( 表示开区间,[ 表示闭区间,默认是一个闭区间,但是此处的写法比较奇葩。
  • 一个好的设计,是符合直觉的,越符合直觉,学习成本就越低,既然已经这么设定了,只能遵循这样的规则。后面想要修改很难,需要考虑兼容性。
  • 广泛使用的软件,一但在新版本中,引入和之前不兼容的特性,成本是非常高的。
    • 考虑兼容性的案例:C++ 兼容 C 语言。
    • 不考虑兼容性的案例:IPV6 不兼容 IPV4
    • 一般来说,确实需要做出这种不兼容的修改,可以先把这个要修改的内容,标记成 “弃用”,给程序员打个预防针,同时推出新版本的方案。

在这里插入图片描述

  • min 和 max 是可以写成浮点数 (zset 分数本身就是浮点数),在浮点数中,存在两个特殊的数值:-inf 负无穷大,inf 无穷大,zset 分数也是支持使用 -inf 和 inf 作为 min 和 max 的。
  • 注意:负无穷大不是无穷小,而无穷小指的是无限趋近于 0 的数。

zrange、zrevrange、zrangebyscore

  • zrange:返回指定区间里的元素,分数按照升序。带上 WITHSCORES 可以把分数也返回。
  • 语法:zrange key start stop [WITHSCORES]
  • 时间复杂度:O(logN + M),N 是 zset 中元素的个数,M 是区间中元素的个数。
  • 返回值:区间内的元素列表。

在这里插入图片描述

  • zrevrange:返回指定区间里的元素,分数按照降序。带上 WITHSCORES 可以把分数也返回。
  • 语法:zrevrange key start stop [WITHSCORES]
  • 时间复杂度:O(logN + M),N 是 zset 中元素的个数,M 是区间中元素的个数。
  • 返回值:区间内的元素列表。

在这里插入图片描述

注意:第一个元素的下标是 0,最后一个元素的下标是 len - 1,也可以使用 -1 代替,且 zrevrange 的区间和 zrange 的区间两个参数的顺序是一样的,即二者区间的使用是一样的,只不过得出结果的顺序不一样。

  • zrangebyscore:返回分数在 min 和 max 之间的元素个数,默认情况下,min 和 max 都是包含的。但是可以通过 ( 进行排除。和 zcount 类似。
  • 语法:zrangebyscore key min max [WITHSCORES] [LIMIT offset count]
    • WITHSCORES:将分数也返回。
    • LIMIT offset count:从偏移量 offset 开始,返回 count 个元素。
  • 时间复杂度:O(logN + M),N 是 zset 中元素的个数,M 是区间中元素的个数。
  • 返回值:区间内的元素列表。

在这里插入图片描述
在这里插入图片描述

注意:zrevrange、zrangebyscore 这两个命令在 Redis 6.2.0 之后废弃,并且功能合并到 zrange 中。

zpopmax、zpopmin

  • zpopmax:删除并返回分数最高的 count 个元素。
  • 语法:zpopmax key [count]
  • 时间复杂度:O(logN * M),N 是 zset 的元素个数,M 是要删除的元素个数。
    • 此处在有序集合删除最大值,就相当于最后一个元素 (尾删),既然是尾删,为什么我们不把这个最后一个元素的位置特殊记录下来,后续删除不就可以做到 O(1) 了嘛?省去了查找过程,但是 Redis 并没有这么做。
    • 事实上 Redis 源码中,针对有序集合,确实记录了尾部这样的特点位置,但是实际删除的时候,并没有用上这个特性,而是直接调用了一个 “通用的删除函数”,给点一个 member 的值,进行查找,找到位置之后再删除。
    • 虽然存在这样的优化空间,但是未来真的会这么优化,也不好说。优化这种活,要优化到刀刃上,优化一般是要先找到性能瓶颈,再针对性的进行优化。
    • 因为当前的这个 logN 的速度其实是不慢的,如果 N 不是非常夸张的大,基本可以近似看作 O(1) 的。
  • 返回值:分数和元素列表。

在这里插入图片描述
在这里插入图片描述

如果存在多个元素的分数相同,同时为最大值时,zpopmax 删除的时候,仍然值删除其中一个元素,会按照 member 字符串的字典序决定删除的先后顺序。

  • zpopmin:删除并返回分数最低的 count 个元素。
  • 语法:zpopmin key [count]
  • 时间复杂度:O(logN * M),N 是 zset 的元素个数,M 是要删除的元素个数。
    • 此处的 zpopmin 和 zpopmax 的逻辑是一样的 (同一个函数实现的),虽然 Redis 的有序集合记录了开头的元素,但是删除的时候,使用的是通用的删除函数,导致出现了重新查找的过程。
  • 返回值:分数和元素列表。

在这里插入图片描述

zrank、zrevrank、zscore

  • zrank:返回指定元素的排名 (类似下标),升序。
  • 语法:zrank key member
  • 时间复杂度:O(logN)
  • 返回值:排名。

在这里插入图片描述

在 zcount 计算的时候,就是先根据分数找到元素,再根据元素获取到排名,最后把排名相减,就可以得到区间中元素的个数。

  • zrevrank:返回指定元素的排名 (类似下标),降序。
  • 语法:zrevrank key member
  • 时间复杂度:O(logN)
  • 返回值:排名。

在这里插入图片描述

  • zscore:查询指定元素的分数。
  • 语法:zscore key member
  • 时间复杂度:O(1)
    • 前面根据 member 找元素,都是 O(logN),这里也是先要找元素,为什么是 O(1)?此处相当于 Redis 对应这样的查询操作做了特殊优化,付出了额外的空间代价。
  • 返回值:分数。

在这里插入图片描述

zrem、zremrangebyrank、zremrangebyscore

  • zrem:删除指定的元素。
  • 语法:zrem key member [member ...]
  • 时间复杂度:O(logN * M),N 是 zset 的元素个数,M 是要删除的元素个数。
  • 返回值:本次操作删除的元素个数。

在这里插入图片描述

  • zremrangebyrank:按照排序,升序删除指定范围的元素,左闭右闭。
  • 语法:zremrangebyrank key start stop
  • 时间复杂度:O(logN + M),N 是 zset 的元素个数,M 是要删除的区间中元素个数。
    • 此处的查找只需要进行一次,不需要重复进行,之后的元素是紧紧挨着的。
  • 返回值:本次操作删除的元素个数。

在这里插入图片描述

  • zremrangebyscore:按照分数删除指定范围的元素,左闭右闭。
  • 语法:zremrangebyscore key min max
  • 时间复杂度:O(logN + M),N 是 zset 的元素个数,M 是要删除的区间中元素个数。
  • 返回值:本次操作删除的元素个数。

在这里插入图片描述

zincrby

  • zincrby:为指定的元素的关联分数添加指定的分数值。
  • 语法:zincrby key increment member
  • 时间复杂度:O(logN)
  • 返回值:增加后元素的分数。

在这里插入图片描述

注意:不光会修改分数内容,也能同时移动位置,保持整个有序集合仍然是升序的。

阻塞版本命令:bzpopmax、bzpopmin

针对 list 的 blpop、brpop 命令,实现类似阻塞队列的效果,我们这里的 “有序集合” 也可以视为是一个 “优先级队列”,有的时候,也需要一个带有 “阻塞功能” 的优先级队列。

  • bzpopmax:zpopmax 的阻塞版本。
    • 阻塞是在有序集合为空的时候触发的,阻塞直到有其他客户端插入元素。
  • 语法:bzpopmax key [key ...] timeout
    • key:都是一个有序集合 zset
    • timeout:超时时间,单位是秒,且支持小数。
  • 时间复杂度:O(logN),N 是 zset 的元素个数。
  • 返回值:哪个 zset、member 和 score

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果有序集合中已经存在元素了,直接就能返回了,就不会阻塞了。

  • bzpopmin:zpopmin 的阻塞版本。
  • 语法:bzpopmin key [key ...] timeout
  • 时间复杂度:O(logN),N 是 zset 的元素个数。
  • 返回值:哪个 zset、member 和 score

集合间操作:zinterstore、zunionstore

在 set 中,存在 sinter、sunion、sdiff 这些命令求交集、并集、差集操作。而在 zset 中的 zinter、zunion、zdiff 这些命令是从 Redis 6.2 开始支持的,这里使用的是 Redis 5 版本,此处不涉及,但是 Redis 提供了 zinterstore、zunionstore 命令求交集和并集。

有序集合的交集操作

在这里插入图片描述

  • zinterstore:求出给定有序集合中元素的交集并保存进目标有序集合中,在合并过程中以元素为单位进行合并,元素对应的分数按照不同的聚合方式和权重得到新的分数。
  • 语法:zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
    • numkeys:整数,描述了后续有几个 key 参与交集运算。
      • 前面 set 介绍的命令,不涉及到类似于此处的设定,主要是因为 numkeys 描述出 key 的个数之后,就可以明确的知道,后面的 “选项” 是从哪里开始的,避免选项和 key 混淆。
      • 例如:HTTP 协议的请求报头中的 Content-Length 描述了正文的长度,防止数据产生的黏包问题,HTTP 协议在传输层是基于 TCP 实现的,而 TCP 是面向字节流的,黏包问题是面向字节流这种 IO 方式中的一个普遍存在的问题。
      • 同理文件读写也是面向字节流的,解决黏包问题的关键在于明确包的长度/边界。对于有正文的 HTTP 请求,Content-Length 就是包的长度;而对于没有正文的 HTTP 请求,空行就是包的边界。
    • weights:权重,合并生成的有序集合是带有分数的,此处指定的权重,相当于一个系数,会乘以当前的分数。
    • aggregate:总计最终 score 的方式。
      • 有序集合中,member 才是元素的本体,score 只是辅助排序的工具人,因此,在进行比较 “相同” 的时候,只要 member 相同即可,score 不一样不影响。
      • 如果 member 相同,score 不同,进行交集合并之后,最终的 score,就是根据这里的 aggregate 来计算 (求和/取最大/取最小)
  • 时间复杂度:O(N * K) + O(M * logM),N 是输入的有序集合中,最小的有序集合的元素个数;K 是输入的个有序集合个数;M 是最终结果的有序集合的元素个数。
    • 这个东西取决于 Redis 源码如何实现的,这里的 K 一般不会很多,可以近似看作 1,化简一下,认为 N 和 M 是接近的 (同一个数量级,假设不严谨,只是近似看来),最终就是 O(M) + O(M * logM) 近似 O(M * logM),
  • 返回值:目标集合中的元素个数。

在这里插入图片描述

默认情况是相加,如下:
在这里插入图片描述

只使用 weights,默认情况是先乘权重系数,再相加,如下:
在这里插入图片描述

只使用 aggregate 取最小、取最大、求和,如下:
在这里插入图片描述

同时使用 weight 和 aggregate 取最小、取最大、求和,如下:
在这里插入图片描述

有序集合的并集操作

在这里插入图片描述

  • zunionstore:求出给定有序集合中元素的并集并保存进目标有序集合中,在合并过程中以元素为单位进行合并,元素对应的分数按照不同的聚合方式和权重得到新的分数。
  • 语法:zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
  • 时间复杂度:O(N) + O(M * logM),N 是输入的有序集合总的元素个数;M 是最终结果的有序集合的元素个数。
  • 返回值:目标集合中的元素个数

在这里插入图片描述

默认情况是相加,如下:
在这里插入图片描述

只使用 weights,默认情况是先乘权重系数,再相加,如下:
在这里插入图片描述

只使用 aggregate 取最小、取最大、求和,如下:
在这里插入图片描述
在这里插入图片描述

同时使用 weight 和 aggregate 取最小、取最大、求和,如下:
在这里插入图片描述
在这里插入图片描述

三. zset 命令小结

命令执行效果时间复杂度
zadd key [NX/XX] [CH] [INCR] score member [score member …]向有序集合中添加元素O(K * logN)
zcard key获取有序集合中元素的个数O(1)
zcount key min max获取有序集合 [min, max] 区间内的元素logN
zrange key start stop [WITHSCORES]获取有序集合中的元素,升序O(logN + M)
zrevrange key start stop [WITHSCORES]获取有序集合中的元素,降序O(logN + M)
zrangebyscore key min max [WITHSCORES] [LIMIT offset count]按照分数获取有序集合 [min, max] 区间内的元素O(logN + M)
zpopmax key [count]删除并返回分数最高的 count 个元素O(logN + M)
zpopmin key [count]删除并返回分数最低的 count 个元素O(logN + M)
zrank key member返回有序集合中元素的排名,升序O(logN)
zrevrank key member返回有序集合中元素的排名,降序O(logN)
zscore key member查询指定元素的分数O(1)
zrem key member [member …]删除指定的元素O(logN + M)
zremrangebyrank key start stop按照排序,升序删除指定范围的元素O(logN + M)
zremrangebyscore key min max按照分数删除指定范围的元素O(logN + M)
zincrby key increment member为指定的元素的关联分数添加指定的分数值O(logN)
bzpopmax key [key …] timeoutzpopmax 的阻塞版本O(logN)
bzpopmin key [key …] timeoutzpopmin 的阻塞版本O(logN)
zinterstore destination numkeys key [key …] [WE/GHTS weight] [AGGREGATE SUM/MIN/MAX]将交集存储在目标有序集合中O(N * K) + O(M * logM)
zunionstore destination numkeys key [key …] [WE/GHTS weight] [AGGREGATE SUM/MIN/MAX]将并集存储在目标有序集合中O(N) + O(M * logM)

其中 N 是有序集合中元素的个数,M 是区间中元素的个数/要删除的元素的个数。

四. zset 内部编码方式

有序集合类型的内部编码有两种:

  • ziplist (压缩列表):当有序集合的元素个数小于 zset-max-ziplist-entries 配置 (默认 128 个),同时每个元素的值都小于 zset-max-ziplist-value 配置 (默认 64 字节) 时,Redis 会用 ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使用。
    • 如果有序列表中的元素个数比较少,或者单个元素体积较小,使用 ziplist 来存储,做到节省空间,但是效率会下降。
  • skiplist (跳表):当 ziplist 条件不满足时,有序集合会使用 skiplist 作为内部实现,因为此时 ziplist 的操作效率会下降。
    • 如果有序列表中的元素个数比较多,或者单个元素体积较大,使用 skiplist 来存储,做到提高效率。
    • 简单来说,跳表是一个 “复杂链表”,查询一个元素的时间复杂度是 logN,相比于树形结构 (平衡二叉搜索树),更适合按照范围获取元素,功能类似于 MySQL 数据库低层的 B+ 树。

可以使用 object encoding 命令,来查看当前有序集合的内部编码方式,如下:

在这里插入图片描述

五. zset 使用场景

排行榜系统

  • 有序集合比较典型的使用场景就是排行榜系统,例如:微博热搜、游戏天梯排行、成绩排行。
  • 榜单的维度可能是多方面的:按照时间、按照阅读量、按照点赞量。用来排行的 “分数” 是实时变化的,使用 zset 来完成上述操作,就非常的简单、高效的更新排行。
    • 比如:游戏天梯排行,只需要把玩家信息和对应的分数给放到有序集合中即可,自动就形成了一个排行榜,随着可以按照排行 (下标)、按照分数,进行范围查找,随着分数发生改变,也可以比较方便的使用 zincrby 修改分数,排行顺序也能自动调整。
    • 但是游戏玩家这么多,此时都用 zset 来在内存中存储,能存的下嘛?假设 userId 按照 4 个字节计算,score 按照 8 个字节计算,表示一个玩家就是 12 个字节,若存在 1 亿个玩家就是 12 亿字节,约等于 1.2 GB,即便是家用电脑都能够存下,更何况公司的服务器。
    • 对于游戏排行榜,这里的先后顺序非常容易确定,但是有的排行榜就要复杂一些,比如:微博热点,是一些综合的体现 (浏览量、点赞量、转发量、评论量),使用权重 weight 分配,具体有多少个维度,每个维度权重该怎么分配,以及怎么设定是最优的,公司团队通过人工智能的方式来进行计算,根据每个维度,计算得到的综合得分,就是热度。
    • 此时就可以借助 zinterstore / zunionstore 按照加权方式处理,把上述每个维度的数值都放到一个有序集合中,member 就是微博的 id,score 就是某个维度的数值,按照约定好的权重,进行集合间运算即可,得到的结果集合的分数就是热度,此时排行榜也就出来了。
    • 实现排行榜,zset 是一个选择,但不是说非得用 Redis 中的 zset,有些场景确实可以用到有序集合,但不方便使用 Redis,此时可以考虑使用其他方式的有序集合 (第三方库、自己基于跳表实现有序集合)

本例中我们使用点赞数这个维度,维护每天的热榜:

  • 添加用户赞数:用户 james 发布了一篇文章,并获得 3 个赞,可以使用有序集合的 zadd 和 zincrby 功能。之后如果再获得赞,可以使用 zincrby:
zadd user:ranking:2022-03-15 3 james
zincrby user:ranking:2022-03-15 1 james
  • 取消用户赞数:由于各种原因 (例如用户注销、用户作弊等) 需要将用户删除,此时需要将用户从榜单中删除掉,可以使用 zrem。例如删除成员 tom:
zrem user:ranking:2022-03-15 tom
  • 展示获取赞数最多的 10 个用户:此功能使用 zrevrange 命令实现:
zrevrangebyrank user:ranking:2022-03-15 0 9
  • 展示用户信息以及用户分数:次功能将用户名作为键后缀,将用户信息保存在哈希类型中,至于用户的分数和排名可以使用 zscore 和 zrank 来实现:
hgetall user:info:tom
zscore user:ranking:2022-03-15 mike
zrank user:ranking:2022-03-15 mike

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/83732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mermaid 绘图--以企业权限视图为例

文章目录 一、示例代码二、基础结构设计2.1 组织架构树2.2 权限视图设计 三、销售数据权限系统四、关键语法技巧汇总 一、示例代码 在企业管理系统开发中,清晰的权限视图设计至关重要。本文将分享如何使用 Mermaid 绘制直观的企业权限关系图,复制以下代…

[pdf、epub]300道《软件方法》强化自测题业务建模需求分析共257页(202505更新)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 在本账号CSDN资源下载,或者访问链接: http://www.umlchina.com/url/quizad.html 如果需要提取码:umlc 文件夹中的“300道软件方法强化自测题2025…

std__map,std__unordered_map,protobuf__map之间的性能比较

简单比较下 std::map、std::unordered_map 和 protobuf::Map 的性能,主要关注在 插入、查找 和 删除 操作上的效率以及内存管理的差异。 std::map 底层实现:std::map 使用红黑树作为底层数据结构,红黑树是一种平衡二叉查找树的变体结构&…

文档处理组件Aspose.Words 25.5全新发布 :六大新功能与性能深度优化

在数字化办公日益普及的今天,文档处理的效率与质量直接影响到企业的运营效率。Aspose.Words 作为业界领先的文档处理控件,其最新发布的 25.5 版本带来了六大新功能和多项性能优化,旨在为开发者和企业用户提供更强大、高效的文档处理能力。 六…

Three.js + Vue3 加载GLB模型项目代码详解

本说明结合 src/App.vue 代码,详细解释如何在 Vue3 项目中用 three.js 加载并显示 glb 模型。 1. 依赖与插件导入 import {onMounted, onUnmounted } from vue import * as THREE from three import Stats from stats.js import {OrbitControls } from three/examples/jsm/co…

Flutter如何支持原生View

在 Flutter 中集成原生 View(如 Android 的 SurfaceView、iOS 的 WKWebView)是通过 平台视图(Platform View) 实现的。这一机制允许在 Flutter UI 中嵌入原生组件,解决了某些场景下 Flutter 自身渲染能力的不足&#x…

vue-11(命名路由和命名视图)

命名路由和命名视图 命名路由和命名视图提供了组织和导航 Vue.js 应用程序的强大方法,尤其是在它们的复杂性增加时。它们提供了一种语义更合理、可维护的路由方法,使您的代码更易于理解和修改。命名路由允许您按名称引用路由,而不是依赖 URL…

微软认证考试科目众多?该如何选择?

在云计算、人工智能、数据分析等技术快速发展的今天,微软认证(Microsoft Certification)已成为IT从业者、开发者、数据分析师提升竞争力的重要凭证。但面对众多考试科目,很多人不知道如何选择。本文将详细介绍微软认证的考试方向、…

视频汇聚平台EasyCVR“明厨亮灶”方案筑牢旅游景区餐饮安全品质防线

一、背景分析​ 1)政策监管刚性需求​:国家食品安全战略及 2024年《关于深化智慧城市发展的指导意见》要求构建智慧餐饮场景,推动数字化监管。多地将“AI明厨亮灶”纳入十四五规划考核,要求餐饮单位操作可视化并具备风险预警能力…

Mysql莫名奇妙重启

收到客户反馈有时接口报504,查看应用日志发现故障期间数据库连接失败 com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failureThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not receive…

半监督学习:低密度分离假设 (Low-Density Separation Assumption)

半监督学习(SSL)的目标是借助未标记数据辅助训练,以期获得比仅用带标签的监督学习范式更好的效果。但是,SSL的前提是数据分布需满足某些假设。否则,SSL可能无法提升监督学习的效果,甚至会因误导性推断降低预测准确性。 半监督学习…

Python Day44

Task: 1.预训练的概念 2.常见的分类预训练模型 3.图像预训练模型的发展史 4.预训练的策略 5.预训练代码实战:resnet18 1. 预训练的概念 预训练(Pre-training)是指在大规模数据集上,先训练模型以学习通用的特征表示&am…

vue3 eslint ts 关闭多单词命名检查

无效做法 import { globalIgnores } from eslint/config import {defineConfigWithVueTs,vueTsConfigs, } from vue/eslint-config-typescript import pluginVue from eslint-plugin-vue import skipFormatting from vue/eslint-config-prettier/skip-formatting// To allow m…

贪心,回溯,动态规划

1.贪心算法 ​ 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望全局最好或是最优的算法。 特点 局部最优选择不能保证全局最优高效 适用条件 局部最优可以导致全局最优问题的最优解包含子问题的最优解 经典问题 活动选择问题最短路径最…

【Netty4核心原理⑧】【揭开Bootstrap的神秘面纱 - 服务端Bootstrap❶】

文章目录 一、前言二、流程分析1. 创建 EventLoopGroup2. 指定 Channel 类型2.1 Channel 的创建2.2 Channel 的初始化 3. 配置自定义的业务处理器 Handler3.1 ServerBootstrap#childHandler3.2 handler 与 childHandler 的区别 4. 绑定端口服务启动 三、bossGroup 与 workerGro…

为什么需要自动下载浏览器驱动?

为什么需要自动下载浏览器驱动? 血泪场景重现 新人入职第一天: 花3小时配置Chrome/Firefox驱动版本不匹配导致SessionNotCreatedException 浏览器自动更新后: 所有测试脚本突然崩溃手动查找驱动耗时长 终极解决方案:自动下载驱…

NLP常用工具包

✨做一次按NLP项目常见工具的使用拆解 1. tokenizer from torchtext.data.utils import get_tokenizertokenizer get_tokenizer(basic_english) text_sample "Were going on an adventure! The weather is really nice today." tokens tokenizer(text_sample) p…

在 Vue 的template中使用 Pug 的完整教程

在 Vue 的template中使用 Pug 的完整教程 引言 什么是 Pug? Pug(原名 Jade)是一种高效的网页模板引擎,通过缩进式语法和简洁的写法减少 HTML 的冗长代码。Pug 省略了尖括号和闭合标签,使用缩进定义结构,…

【Android基础回顾】四:ServiceManager

Android 中的 ServerManager 是 Android 框架中一个用于管理系统服务的核心机制。它是 Binder IPC 的一部分,用于在客户端和服务端之间建立联系,广泛应用于系统服务(如 ActivityManager、WindowManager 等)的注册与获取。 1 Serv…

【Android基础回顾】一:Binder机制是什么?有什么用?

Android中的Binder机制是Android系统中最核心和最基础的进程间通讯机制。 1 什么是进程间通讯机制(IPC)? 众所周知,Android系统基于Linux开发,Linux系统里面本来就有进程间通讯机制。 1.1 Linux的IPC(Inter-Process Communication)概览 它…