【Redis】string 类型

string

  • 一. string 类型介绍
  • 二. string 命令
    • set、get
    • mget、mset
    • setnx、setex、psetex
    • incr、incrby、decr、decrby、incrbyfloat
    • append、getrange、setrange、strlen
  • 三. string 命令小结
  • 四. string 内部编码方式
  • 五. string 的应用场景
    • 缓存功能
    • 计数功能
    • 共享会话
    • 手机验证码
  • 六. 什么是业务

一. string 类型介绍

  • Redis 所有的 key 都是字符串,value 的类型是存在差异的。
  • 由于 Redis 内部存储字符串完全是按照二进制流的形式保存的,所以 Redis 不是不处理字符集编码问题的,客户端传入的命令中使用的是什么字符集编码,就存储什么字符集编码。
    • 不仅仅可以存储文本数据,还可以存整数、普通的文本字符串、JSON、XML、二进制数据 (图片、音频、视频)
    • 音频、视频体积可能会比较大,Redis 对于 string 类型,限制了大小最大是 512 M
    • Redis 是单线程模型,希望进行的操作都能比较快速,如果存储音频、视频可能处理的速度慢,导致 Redis 被阻塞了。
    • MySQL 5.7 及以前版本,默认的字符集是拉丁文,插入中文就会失败。
    • Redis 一般来说,遇到乱码问题的概率更小。
      在这里插入图片描述

二. string 命令

set、get

  • set:将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,无论原来的数据类型是什么,之前关于此 key 的 TTL 也全部失效。
  • 语法:set key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]
  • 时间复杂度:O(1)

set 命令支持多种选项来影响它的行为:

  • EX seconds:使用秒作为单位设置 key 的过期时间。
  • PX milliseconds:使用毫秒作为单位设置 key 的过期时间。
  • NX:只在 key 不存在时才进行设置,即如果 key 之前已经存在,设置不执行。
  • XX:只在 key 存在时才进行设置,即如果 key 之前不存在,设置不执行。

注意:

  • Redis 文档给出的语法说明格式:[] 相当于一个独立的单元,表示可选项 (可有可无的),其中 | 表示或者的意思,多个只能出现一个,[] 和 [] 之间是可以同时存在的。
  • 由于带选项的 SET 命令可以被 SETNX、SETEX、PSETEX 等命令代替,所以之后的版本中,Redis 可能进行合并。

返回值:

  • 如果设置成功,返回 OK
  • 如果由于 SET 指定了 NX 或者 XX 但条件不满足,SET 不会执行,并返回 nil

一个快速失去年终奖的小技巧:

  • 清除 Redis 上所有的数据,删库,对于 MySQL 就是 drop database
  • flushall 可以把 Redis 上的所有键值对都带走。
  • 以后在公司,尤其是生产环境的数据库,千万千万不敢敲,当前学习阶段,敲一敲倒无所谓。

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

  • get:获取 key 对应的 value,如果 key 不存在,返回 nil,如果 value 的数据类型不是 string,会报错。
  • 语法:get key
  • 时间复杂度:O(1)
  • 返回值:当 key 存在时返回对应的 value,当 key 不存在时返回 nil

在这里插入图片描述

mget、mset

  • mset:一次性设置多个 key 的值。
  • 语法:mset key value [key value ...]
  • 时间复杂度:O(N),N 是 要设置的 key 数量,一般设置不了太多,可以看作 O(1)
  • 返回值:永远是 OK

需要注意的是,如果一次性设置太多 key,例如 10w 个键值对,可能会导致 Redis 阻塞。

在这里插入图片描述

  • mget:一次性获取多个 key 的值,如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil
  • 语法:get key [key ...]
  • 时间复杂度:O(N),N 是 要设置的 key 数量,一般设置不了太多,可以看作 O(1)
  • 返回值:对应 value 的列表。

在这里插入图片描述

多次 get VS 单次 mget

在这里插入图片描述

使用 mget/mset 由于可以有效地减少了网络时间,所以性能相较更高。1000 次 get 和 1 次 mget 对比,如下表:

在这里插入图片描述

学会使用批量操作,可以有效提高业务处理效率,但是要注意,每次批量操作所发送的键的数量也不是无节制的,否则可能造成单一命令执行时间过长,导致 Redis 阻塞。

setnx、setex、psetex

  • setnx:不存在才能设置,存在则设置失效。
  • setex:设置 key 的过期时间,单位是秒。
  • psetex:设置 key 的过期时间,单位是毫秒。

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

  • 针对 set 一些的常用用法,进行了缩写,之所以这样搞,就是为了让操作更符合人的直觉 (使用这的门槛越低,要背的东西就越少)
    • 符合人的直觉,编程语言中,很多关键字都是和自然语言相关的。
    • 后续我们去设计一些库、工具,代码给别人使用的时候,也尽量符合直觉,不要设计的 “反人类” / “反直觉”。

incr、incrby、decr、decrby、incrbyfloat

  • incr:将 key 对应的 value 表示的数字加 1 操作,如果 key 不存在,则视为 key 对应的 value 是 0,如果 key 对应的 value 不是一个整型或者范围超过了 64 位有符号整型 (long long),则报错。
  • 语法:incr key
  • 时间复杂度:O(1)
  • 返回值:value 加完后的数值。

注意:如果 incr 操作的 key 不存在,就会把这个 key 的 value 当做 0 来使用。

在这里插入图片描述

  • incrby:将 key 对应的 value 表示的数字加 n 操作。
  • 语法:incrby key increment
  • decr:将 key 对应的 value 表示的数字减 1 操作。
  • 语法:decr key
  • decrby:将 key 对应的 value 表示的数字减 n 操作。
  • 语法:decrby key decrement
  • incrbyfloat:将 key 对应的 value 表示的数字加一个浮点数操作。
  • 语法:incrbyfloat key increment
    • incrbyfloat 只能用加上负数的形式,充当减法操作。
    • 虽然此处没有提供减法版本的命令,但是使用 Redis 进行的计数操作,一般都是针对整数进行操作的。
    • 上述操作的时间复杂度都是 O(1),功能都是类似的。
    • 由于 Redis 处理命令的时候,是单线程模型,多个客户端同时针对同一个 key 进行 incr 操作,不会引起类似 “线程安全” 的问题。
    • 很多存储系统和编程语言内部使用 CAS 制实现计数功能,会有一定的 CPU 开销,但在 Redis 中完全不存在这个问题,因为 Redis 是单线程架构,任何命令到了 Redis 服务端都要顺序执行。

append、getrange、setrange、strlen

字符串,也支持一些常用的操作,例如:拼接、获取、修改字符串的部分内容,获取字符串的长度。

append

  • append:如果 key 已经存在,并且对应的 value 是一个字符串,命令会将新增的字符串追加到有字符串的后边,如果 key 不存在,则效果等同于 set 命令。
  • 语法:append key value
  • 时间复杂度:O(N)。追加的字符串一般长度较短,可以视为 O(1)。
  • 返回值:追加完成之后的字符串的长度。

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

  • append 的返回值,长度的单位是字节,Redis 的字符串,不会对字符编码做任何处理 (不认字符,只认字节)
    • 当前我们的 XShell 终端默认的编码是 utf8,在终端中输入汉字之后,也就是按照 utf8 编码的,一个汉字在 utf8 字符集中,通常是 3 个字节。
    • 抛开编码方式,谈一个汉字所占的字节数,都是扯蛋。
  • 使用 get 获取 key 对应的 value 为汉字的字符串时,获取到的是 utf8 编码,对应的十六进制的方式表现出来。
    • 你好,这两个汉字的 utf8 编码是:E4BDA0E5A5BD

在这里插入图片描述

  • 在启动 Redis 客户端的时候,加上一个 --raw 这样的选项,就可以是 Redis 客户端能够自动把二进制数据尝试翻译。
    • 这里退出 Redis 客户端的方式是:Ctrl + d,或者 quit
    • 操作 Linux 的时候,千万要注意,不要乱按 Ctrl + s,否则在 XShell 中会 “冻结当前画面”,需要 Ctrl + q,“解除冻结”。

getrange

  • getrange:返回 key 对应的 value 字符串的子串,由 start 和 end 确定 (左闭右闭),可以使用负数表示倒数,-1 代表倒数第一个字符,-2 代表倒数第二个,其他的与此类似,超过范围的偏移量会根据字符串的长度调整成正确的值。
  • 语法:getrange key start end
  • 时间复杂度:O(N)。N 为 [start,end] 区间的长度,由于字符串通常比较短,可以视为是 O(1)。
  • 返回值:string 类型的子串。

在这里插入图片描述

  • 编程这个大圈子中,区间大多数都是 “左闭右开”,但是确实有特殊情况,例如就是 Redis
  • 与 C++ 一样的是,第一个字符的下标是 0

在这里插入图片描述

  • 如果字符串中保存的是汉字,此时进行子串切分,很可能切出来的就不是完整的汉字了,切出的结果在 utf8 码表中不知道能查出什么了。
    • 上述的问题,在 C++ 中也同样存在,因为字符串的基本单位都是字节,C++ 这里头对于汉字的处理是没那么完善的,就需要程序员手动处理了,在 utf8 编码中需要按照 3 个字节处理。
    • 在 Java 就没事,因为字符串的基本单位都是字符 (占 2 个字节),Java 中的 String 帮我们把汉字的编码转换都处理好了。

setrange

  • setrange:从指定的偏移开始,覆盖 key 对应的 value 字符串的⼀部分。
  • 语法:setrange key offset value
  • 时间复杂度:O(N)。N 为 value 的长度,由于一般给的 value 比较短,通常视为 O(1)。
  • 返回值:替换后的字符串的长度。

在这里插入图片描述

  • 如果当前我们的 value 是一个中文字符串,那么进行 setrange 的时候,是可能会搞出问题的。
  • setrange 针对不存在的 key 也是可以操作的,不过会把 offset 之前的内容填充成 0x00
    • 凭空生成的一个字节,这个字节里面的内容就是 0x00,aaa 被追加到 0x00 后面了,如下:

在这里插入图片描述

strlen

  • strlen:获取 key 对应的 value 字符串的长度,当 key 存放的不是字符串时,报错。
  • 语法:strlen key
  • 时间复杂度:O(1)
  • 返回值:字符串的长度,或者当 key 不存在时,返回 0

在这里插入图片描述

  • Redis 中的 strlen 获取字符串的长度,单位是字节。
    • MySQL 中的 varchar(N) 数据类型是按照字符为单位的,MySQL 中的字符,也是完整的汉字,这样的一个字符,有可能是多个字节。
    • C++ 中,字符串长度的本身使用字节为单位的。
    • Java 中,字符串长度的本身使用字符为单位的。
      • Java 中的 char,使用的是 unicode 编码,一个汉字等价于 2 个字节。
      • Java 中的 String,使用的是 utf8 编码,一个汉字等价于 3 个字节。
      • Java 的标准库内部,在进行上述的操作时,程序员一般是感知不到编码方式的变换的。

三. string 命令小结

命令执行效果时间复杂度
set key value设置 key 的值是 valueO(1)
get key获取 key 的值 valueO(1)
del key [key …]删除指定的 keyO(k),k 是键的个数
mset key value [key value …]批量设置指定的 key 和 valueO(k),k 是键的个数
mget key [key …]批量获取 key 的值O(k),k 是键的个数
incr key指定的 key 的值 + 1O(1)
decr key指定的 key 的值 - 1O(1)
incrby key n指定的 key 的值 + nO(1)
decrby key n指定的 key 的值 - nO(1)
incrbyfloat key n指定的 key 的值 + nO(1)
append key value指定的 key 的值追加 valueO(1)
strlen key获取指定 key 的值 value 的长度O(1)
getrange key start end获取指定 key 的从 start 到 end 的部分字符串O(n),n 是字符串长度
setrange key offset value覆盖指定 key 的从 offset 开始的部分字符串O(n),n 是字符串长度
  • 字符串类型命令的效果、时间复杂度,开发人员可以参考此表,结合自身业务需求和数据大小选择合适的命令。
  • 上面的 getrange 和 setrange,由于字符串一般都比较短,通常视为 O(1)。

四. string 内部编码方式

string 内部有 3 中编码方式:

  • int:64 比特位 / 8个字节,的长整型。
  • embstr:压缩字符串,适用于表示,小于等于 39 个字节的字符串。
  • raw:普通字符串,适用于表示,大于 39 个字节的字符串,只是单纯的持有字节数组。

Redis 会根据当前值的类型和长度动态决定使用哪种内部编码实现,可以通过 object encoding key 来查看具体的编码方式。

在这里插入图片描述

  • 不建议大家去记,长度大于 39 这样的数字,若某个业务场景,有很多很多的 key,类型都是 string,但是每个 value 的 string 长度都是 100 左右。
    • 更关注与整体的内存空间,因此,这样的字符串使用 embstr 来存储也不是不能考虑,上述的效果,具体怎么实现呢?
      • 先看 Redis 是否提供了对应的配置项,可以修改 39 这个数字。
      • 如果没有提供这样的配置项,就需要针对 Redis 源码进行魔改。
    • 为什么很多大厂,往往是自己造轮子,而不是直接使用业界成熟的呢,例如:消息队列,RPC 通信框架。
      • 开源的组件,往往考虑的是通用性。
      • 但是大厂往往会遇到一些极端业务场景,往往就需要根据当前的极端业务,针对上述开源组件进行定制化。
      • 往上也经常有种说法,大厂造轮子,一般是为了 KPI

在这里插入图片描述

  • Redis 存储小数,本质上还是当成字符串来存储,这就和整数相比差别很大了,整数直接使用 long long 来存储,比较方便进行算术运算的。
  • 小数则是使用字符串来存储,意味着每次进行算术运算,都需要把字符串转换成小数,进行运算,结果在转换成字符串进行保存。

五. string 的应用场景

缓存功能

比较典型的缓存使用场景,其中 Redis 作为缓冲层,MySQL 作为存储层,绝大部分请求的数据都是从 Redis 中获取,由于 Redis 具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。

Redis + MySQL 组成的缓存存储架构,图如下:

在这里插入图片描述

整体的思路:

  • 应用服务器访问数据的时候,先查询 Redis。
    • 如果 Redis 上的数据存在了,就直接从 Redis 上取数据交给应用服务器,不继续访问数据库了。
    • 如果 Redis 上的数据不存在,再读取 MySQL 数据库,把读到的数据结果,返回给应用服务器,同时,把这个数据也写入 Redis 中。
      • Redis 这样的缓存,经常用来存储 “热点数据”,高频被使用的数据,这个定义方式,结合业务场景有很多种方式。
      • 刚才上述描述的过程中,相当于是把最近使用到的数据作为热点数据 (暗含了一种解设,某个数据一但被使用了,那么很可能在最近这段时间就会被反复使用到)

上述策略,存在一个明显的问题,随着时间的推移,肯定会有越来越多的 key 再 Redis 上访问不到,从而从 MySQL 读取并写入 Redis 了,此时 Redis 中的数据不是就越来越多了嘛?

  • 在把数据写给 Redis 的同时,给这个 key 设置一个过期时间。
  • Redis 在内存不足的时候,提供了 “淘汰策略”,后面再细说。

下面的伪代码模拟了,业务数据访问过程:

  1. 假设业务是根据用户 uid 获取用户信息:
UserInfo getUserInfo(long uid) {// ...
}
  1. 首先从 Redis 获取用户信息,我们假设用户信息保存在 user:info:<uid> 对应的键中:
// 根据 uid 得到 Redis 的键
String key = "user:info:" + uid;// 尝试从 Redis 中获取对应的值
String value = Redis 执⾏命令: get key;// 如果缓存命中(hit)
if (value != null) {// 假设我们的⽤⼾信息按照 JSON 格式存储UserInfo userInfo = JSON 反序列化(value);return userInfo;
}
  1. 如果没有从 Redis 中得到用户信息,及缓存 miss,则进一步从 MySQL 中获取对应的信息,随后写入缓存并返回:
// 如果缓存未命中(miss)
if (value == null) {// 从数据库中,根据 uid 获取用户信息UserInfo userInfo = MySQL 执⾏ SQL: select * from user_info where uid = <uid>// 如果表中没有 uid 对应的用户信息if (userInfo == null) {响应 404return null;}// 将用户信息序列化成 JSON 格式String value = JSON 序列化(userInfo);// 写入缓存,为了防止数据腐烂(rot),设置过期时间为1小时(也就是3600秒)Redis 执⾏命令: set key value ex 3600// 返回用户信息return userInfo;
}

通过增加缓存功能,在理想情况下,每个用户信息,一个小时期间只会有一次 MySQL 查询,极大地提升了查询效率,也降低了 MySQL 的访问数。

在这里插入图片描述

计数功能

许多应用都会使用 Redis 作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理或者落地到其他数据源。例如:视频网站的视频播放次数可以使用 Redis 来完成:用户每播放一次视频,相应的视频播放数就会自增 1

记录视频播放次数,图如下:

在这里插入图片描述

企业为什么老是乐意用户的数据?

  • 统计,为了进一步明确用户的需求,根据需求来改进和迭代产品。
  • Redis 并不擅长数据统计,例如:想统计播放量前 100 的视频有哪些,基于 Redis 搞就很麻烦。
  • 相比之下,如果是 MySQL 用来存储上述的数据,一个 SQL 语句就能搞定。
  • 这里写入统计数据仓库 (MySQL/HDFS) 的步骤,是异步的:
    • 不是说来一个播放请求,就必须立即写入一个数据,如果是这样就会消耗更多的硬件资源,效率低。
    • 写入数据的速度可以慢一些,只需要保证最终将数据写入即可,例如,每隔一段时间,该时间之内,播放了多少次,将最终的数据写入。
// 在 Redis 中统计某视频的播放次数
long incrVideoCounter(long vid) {key = "video:" + vid;long count = Redis 执⾏命令: incr keyreturn counter;
}

在这里插入图片描述

共享会话

Cookie:浏览器存储数据的机制。
Session:服务器存储数据的机制。

Session 分散存储,图如下:

在这里插入图片描述

一个分布式 Web 服务将用户的 Session 信息 (例如用户登录信息) 保存在各自的服务器中,但这样会造成一个问题:出于负载均衡的考虑,分布式服务会将用户的访问请求均衡到不同的服务器上,并且通常无法保证用户每次请求都会被均衡到同一台服务器上,这样当用户刷新一次访问是可能会发现需要重新登录,这个问题是用户无法容忍的。

为了解决这个问题,可以使用 Redis 将用户的 Session 信息进行集中管理,只要保证 Redis 是高可用和可扩展性的,无论用户被均衡到哪台 Web 服务器上,都集中从 Redis 中查询、更新 Session 信息。如下图:

在这里插入图片描述

手机验证码

很多应用出于安全考虑,会在每次进行登录时,让用户输入手机号并且配合给⼿机发送验证码,然后让用户再次输入收到的验证码并进行验证,从而确定是否是用户本人。为了短信接口不会频繁访问,会限制用户每分钟获取验证码的频率,例如一分钟不能超过 5 次,如下图:

在这里插入图片描述

  • 生成验证码。
    • 用户输入一个手机号。
    • 点击获取验证码,限制一分钟之内,最多获取 5 次验证码,或者获取验证码必须间隔 30 秒,主要还是怕用户频繁获取验证码,对于我们的服务器压力过大。
  • 检查验证码。
    • 把短信收到的验证码这一串数,提交到系统中。
    • 系统进行判断验证码是否正确。
  • 像发送短信这样的操作,都是有专门的 SDK 来实现的,也就是第三方提供的短信平台。

此功能可以用以下伪代码说明基本实现思路:

String 发送验证码(phoneNumber) {key = "shortMsg:limit:" + phoneNumber;// 设置过期时间为1分钟(60秒)// 使⽤ NX, 只在不存在 key 时才能设置成功bool r = Redis 执⾏命令: set key 1 ex 60 nxif (r == false) {// 说明之前设置过该手机的验证码了long c = Redis 执⾏命令: incr keyif (c > 5) {// 说明超过了一分钟5次的限制了// 限制发送return null;}}// 说明要么之前没有设置过手机的验证码, 要么次数没有超过5次String validationCode = ⽣成随机的6位数的验证码();validationKey = "validation:" + phoneNumber;// 验证码5分钟(300秒)内有效Redis 执⾏命令: set validationKey validationCode ex 300;// 返回验证码,随后通过手机短信发送给用户return validationCode ;
}// 验证用户输入的验证码是否正确
bool 验证验证码(phoneNumber, validationCode) {validationKey = "validation:" + phoneNumber;String value = Redis 执⾏命令: get validationKey;if (value == null) {// 说明没有这个手机的验证码记录,验证失败return false;}if (value == validationCode) {return true;} else {return false;}
}

以上介绍了使用 Redis 的字符串数据类型可以使用的几个场景,但其适用场景远不止于此,开发人员可以结合字符串类型的特点以及提供的命令,充分发挥自己的想象力,在自己的业务中去找到合适的场景去使用 Redis 的字符串类型。

六. 什么是业务

  • 业务:其实就是一个公司/一个产品,是任何解决一个/一系列问题的。
    • 解决问题的过程,就可以称为业务。
    • 一个公司/产品想要生存,就得赚钱,就得帮助别人解决问题。
  • 不同的公司,不同的产品,不同的业务,就需要不同的技术作为支撑。
  • 业务是非常重要的,很多时候,优化技术解决不了的问题,可以通过优化业务来解决。

例如:培训公司的业务

  • 直播课程、录播课程、日常跟进/作业批改、笔试强训、项目翻转、模拟面试。
  • 校招跟进、offer 筛选、学长内推、租房信息分享。
  • 解决的问题:都是为了学员更好的就业,获取更好的 offer

例如:12306 买火车票。

  • 这个网站背后技术的积累,可以说是全国甚至全世界,独一档的。
  • 由于春运,这个网站支撑的业务是极其恐怖的,抢火车票,拥有超高的并发量。
  • 虽然当时引入了非常多的技术,提高网站的访问速度和可用性,但是在放票的时候,整体的压力还是很大的,还是很容易出现问题的。
    • 假设我要提前一周抢火车票,我就需要在当天 8:00 的时候准时登入 12306 测试买票。
    • 在这个放票的一瞬间,因为抢票的人太多了,就会导致服务器的压力一个就拉满了。
    • 通过一些常规技术手段,优化的效果并不明显,于是有人提出方案:业务优化->分时段放票。
    • 本来是 1 次放所有的票,现在是分 5 次放票,这样就相当于把服务器的压力降低到原来的五分之一了。
    • 全国那么多车次,分 100 次放票,也很容易能做到。

实际开发过程中,必须要结合实际业务场景,做一些技术上的调整,不同的公司,不同的产品,都会有不同的业务,进入公司之后业务是学习的重点。

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

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

相关文章

HTTP/HTTPS与SOCKS5三大代理IP协议,如何选择最佳协议?

在复杂多变的网络环境中&#xff0c;代理协议的选择直接影响数据安全、访问效率和业务稳定性。HTTP、HTTPS和SOCKS5作为三大主流代理协议&#xff0c;各自针对不同场景提供独特的解决方案。本文将从协议特性、性能对比到选型策略&#xff0c;为您揭示如何根据业务需求精准匹配最…

【ArcGIS Pro微课1000例】0071:将无人机照片生成航线、轨迹点、坐标高程、方位角

文章目录 一、照片预览二、生成轨迹点三、照片信息四、查看方位角五、轨迹点连成线一、照片预览 数据位于配套实验数据包中的0071.rar,解压之后如下: 二、生成轨迹点 地理标记照片转点 (数据管理),用于根据存储在地理标记照片文件(.jpg 或 .tif)元数据中的 x、y 和 z 坐…

【C++项目】:仿 muduo 库 One-Thread-One-Loop 式并发服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;C从入门到精通 目录 &#x1f525; 前言 一&#xff1a;&#x1f525; 项目储备知识 &#x1f98b; HTTP 服务器&#x1f98b; Reactor 模型&#x1f380; 单 Reactor 单线程&#xff1a;单I/O多路…

【java】aes,salt

AES&#xff08;高级加密标准&#xff09;是一种对称加密算法&#xff0c;广泛用于数据加密。在使用 AES 加密时&#xff0c;通常会结合盐值&#xff08;Salt&#xff09;来增强安全性。盐值是一个随机生成的值&#xff0c;用于防止彩虹表攻击和提高加密的复杂性。 一、AES 加…

路由器、网关和光猫三种设备有啥区别?

无论是家中Wi-Fi信号的覆盖&#xff0c;还是企业网络的高效运行&#xff0c;路由器、网关和光猫这些设备都扮演着不可或缺的角色。然而&#xff0c;对于大多数人来说&#xff0c;这三者的功能和区别却像一团迷雾&#xff0c;似懂非懂。你是否曾疑惑&#xff0c;为什么家里需要光…

机顶盒CM311-5s纯手机免拆刷机,全网通,当贝桌面

需要用到的工具 安卓手机一台 甲壳虫adb助手&#xff08;安卓app&#xff09; OTG转换线一个&#xff08;或者用usb&#xff0c;typec双头的U盘一个&#xff0c;未测试&#xff09; 8g U盘一个 用到的刷机文件 1.放入手机中的文件 misc recovery 2. 放入U盘根目录 upda…

c/c++类型别名定义

author: hjjdebug date: 2025年 05月 28日 星期三 12:54:25 CST descrip: c/c类型别名定义: 文章目录 1. #define 是宏替换.2. c风格的typedef 通用形式 typedef type_orig alias3. c风格的using 为类型定义别名的一般格式: using alias type_orig4. using 的优点: 可以直接使…

Virtuoso中对GDS文件进行工艺库转换的方法

如果要对相同工艺节点下进行性能评估&#xff0c;可以尝试将一个厂商的GDS文件转换到另一个厂商&#xff0c;不过要注意的是不同厂商&#xff08;比如SMIC和TSMC&#xff09;之间的DRC规则&#xff0c;尽量采用两个DRC中的约束较为紧张的厂商进行设计&#xff0c;以免转换到另外…

Kubernetes 中部署 kube-state-metrics 及 Prometheus 监控配置实战

文章目录 Kubernetes 中部署 kube-state-metrics 及 Prometheus 监控配置实战环境准备创建监控命名空间准备配置文件创建 ServiceAccount配置 RBAC 权限部署 kube-state-metrics部署node_exporter(可选)验证服务账号 TokenPrometheus 配置示例小结验证增加Grafana面板增加prome…

《重塑认知:Django MVT架构的多维剖析与实践》

MVT&#xff0c;即Model - View - Template&#xff0c;是Django框架独特的架构模式。它看似简单的三个字母&#xff0c;实则蕴含着深刻的设计哲学&#xff0c;如同古老智慧的密码&#xff0c;解开了Web应用开发的复杂谜题。 模型&#xff0c;是MVT架构中的数据核心&#xff0…

【JVM】初识JVM 从字节码文件到类的生命周期

初识JVM JVM&#xff08;Java Virtual Machine&#xff09;即 Java 虚拟机&#xff0c;是 Java 技术的核心组件之一。JVM的本质就是运行在计算机上的一个程序&#xff0c;通过软件模拟实现了一台抽象的计算机的功能。JVM是Java程序的运行环境&#xff0c;负责加载字节码文件&a…

人工智能在智能零售中的创新应用与未来趋势

随着电子商务的蓬勃发展和消费者需求的不断变化&#xff0c;零售行业正面临着前所未有的挑战和机遇。智能零售作为零售行业的重要发展方向&#xff0c;通过引入人工智能&#xff08;AI&#xff09;、物联网&#xff08;IoT&#xff09;、大数据和云计算等前沿技术&#xff0c;正…

DeepSeek 赋能智能物流:解锁仓储机器人调度的无限可能

目录 一、智能物流仓储机器人调度现状1.1 传统调度面临的挑战1.2 现有智能调度的进展与局限 二、DeepSeek 技术探秘2.1 DeepSeek 核心技术原理2.2 DeepSeek 的独特优势 三、DeepSeek 在智能物流仓储机器人调度中的创新应用3.1 智能任务分配与调度3.2 路径规划与避障优化3.3 实时…

Vue CLI创建vue项目,安装插件

Vue CLI创建vue项目&#xff0c;安装插件 一、创建项目1. 安装Vue CLI2. 创建项目 二、安装插件routerlesssassjquery 一、创建项目 1. 安装Vue CLI npm install -g vue/cli2. 创建项目 vue create project cd project二、安装插件 router npm install vue-router # 对于 …

小白成长之路-Linux程序管理(二)

文章目录 一、源码包&#xff08;编译&#xff09;安装1.安装前先查看磁盘大小2.压缩包的位置3.执行编译 二、二进制安装三、Linux操作系统启动流程3.1概述3.2启动流程核心阶段1.电源与固件阶段2.引导加载程序3.内核初始化4.systemd初始化进程5. 用户登录阶段 四、systemd管理机…

Ansible模块——Ansible的安装!

Ansible 安装 Ansible 有三种安装方式&#xff0c;源码安装、发行版安装和 Python 安装。 使用发行版安装或 Python 安装两种方式时&#xff0c;Ansible 的安装包有两个&#xff0c;区别如下&#xff1a; • ansible-core&#xff1a;一种极简语言和运行时包&#xff0c;包含…

《全面解析鸿蒙相关概念:鸿蒙、开源鸿蒙、鸿蒙 Next 有何区别》

大家好&#xff0c;这里是程序员晚枫&#xff0c;最近接了一个和鸿蒙电脑有关的商单&#xff0c;所以专门花时间研究了一下和鸿蒙有关的概念。 鸿蒙系统相关概念主要有以下三个&#xff0c;它们之间存在多方面的区别&#xff0c;以下是具体介绍&#xff1a; OpenHarmony 定义…

C# 数组与字符串:全面解析与应用实践

在C#编程语言中&#xff0c;数组和字符串是两种最基础也是最重要的数据类型。无论是简单的控制台应用程序&#xff0c;还是复杂的企业级系统&#xff0c;数组和字符串都扮演着不可或缺的角色。本文将全面深入地探讨C#中数组和字符串的特性、使用方法、性能考量以及实际应用场景…

VR 技术在农业领域或许是一抹新曙光​

在科技日新月异的今天&#xff0c;VR(虚拟现实)技术已不再局限于游戏、影视等娱乐范畴&#xff0c;正逐步渗透到各个传统行业&#xff0c;为其带来全新的发展契机&#xff0c;农业领域便是其中之一。VR 技术利用计算机生成三维虚拟世界&#xff0c;给予用户视觉、听觉、触觉等多…

SPEAR开源程序是用于逼真演示 AI 研究的模拟器

​一、软件介绍 文末提供程序和源码下载 SPEAR开源程序是用于逼真具身 AI 研究的模拟器 二、AI 研究的模拟器 交互式模拟器正在成为训练具体代理的强大工具&#xff0c;但现有的模拟器存在内容多样性、物理交互性和视觉保真度有限的问题。我们通过引入 SPEAR&#xff1a;照片…