Redis String 类型详解:操作命令、底层编码与使用案例

news2024/11/15 10:13:10

文章目录

    • 一 . 常见命令
      • 1.1 set
      • 1.2 get
      • 1.3 mset、mget
      • 1.4 setnx、setex、psetex
      • 1.5 incr、incrby
      • 1.6 decr、decrby、incrbyfloat
      • 1.7 append
      • 1.8 getrange
      • 1.9 setrange
      • 1.10 strlen
      • 小结
    • 二 . string 的编码方式
    • 三 . 应用场景
      • 3.1 缓存
      • 3.2 计数器
      • 3.3 共享会话
      • 3.4 手机验证码

Hello , 大家好 , 这个专栏给大家带来的是 Redis 系列 ! 本篇文章给大家讲解的是 Redis 中 string 类型的相关内容 , 我们会从常见命令、底层编码方式、应用场景三方面给大家介绍

在这里插入图片描述

本专栏旨在为初学者提供一个全面的 Redis 学习路径,从基础概念到实际应用,帮助读者快速掌握 Redis 的使用和管理技巧。通过本专栏的学习,能够构建坚实的 Redis 知识基础,并能够在实际学习以及工作中灵活运用 Redis 解决问题 .
专栏地址 : Redis 入门实践


正文开始

我们目前谈到的数据类型 , 都是针对 value 来说的

Redis 中的字符串 , 直接就是按照二进制数据的方式来存储的 , 我们可以变相的将 string 视为字节数组

底层不会做任何的编码转化 , 也就是说存进去的是什么 , 取出来的就是什么 .

那 Redis 的字符串不仅可以存储文本数据 , 它还可以存储整数、JSON、xml、二进制的数据 (图片 / 视频 / 音频) …

但是视频 / 音频体积可能会比较大 , 而 Redis 对于 string 类型 , 限制了大小最大是 512M

那 Redis 他的底层是不会做任何的编码转换的

我们之前在学习 MySQL 的时候 , 默认的字符集是拉丁文 , 插入中文就会失败 .
而 Redis 存进去什么就是什么 , 直接取出来即可 , 就不用再判断字符集等等

一 . 常见命令

1.1 set

set 的语法 : set key value [ex 超时时间(秒) | px 超时时间(毫秒)] [nx | xx]

Redis 官方文档特殊符号的说明 :
[]就相当于一个独立的单元 , 表示可选项 (可有可无)
| 表示或者 , 多个条件之间只能出现一个
[][]是可以同时存在的

比如 我们的这一条指令 : set key value ex 10 , 他就相当于这两条指令

  1. set key value
  2. expire key 10

另外 , nx 指的是如果 key 不存在 , 才去设置 ; 如果 key 存在 , 则不去设置 (返回 nil)
xx 指的是如果 key 存在 , 才去设置 value (相当于更新操作) ; 如果 key 不存在 , 则不设置 (返回 nil)

那为了方便 set 命令的使用 , Redis 就出了一些简写 , 比如 : setnx、setex、setpx …
还需要注意的是 , 如果 key 不存在 , 那就会创建出新的键值对 , 如果 key 存在 , 则是让新的 value 覆盖旧的 value , 也有可能修改之前的数据类型 , 原来存在的过期时间 (ttl) 也会失效

接下来 , 我们就来模拟一下 set 命令的使用

清除之前的数据 : flushdb / flushall

127.0.0.1:6379> set k1 123 # 设置键值对
OK
127.0.0.1:6379> get k1 # 获取键值对
"123"
127.0.0.1:6379> set k2 123 ex 10 # 设置过期时间为 10s
OK
127.0.0.1:6379> ttl k2 # 获取剩余时间
(integer) 5
127.0.0.1:6379> ttl k2 # 键值对如果过期 , 就会返回 -2
(integer) -2
127.0.0.1:6379> get k2 # 此时再去获取 k2 就获取不到了
(nil)
127.0.0.1:6379> set k3 123 nx # nx 指的是不存在才去创建
OK
127.0.0.1:6379> get k3
"123"
127.0.0.1:6379> set k1 456 nx # 此时 k1 已经存在 , nx 再去创建就会失败 , 返回 nil
(nil)
127.0.0.1:6379> get k1 # 得到的还是旧的值
"123"
127.0.0.1:6379> set k4 666 xx # xx 指的是存在才去创建 (覆盖)
(nil) # 此时 k4 并不存在 , 就会创建失败 , 返回 nil
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> set k3 789 xx # k3 此时存在 , xx 创建就会成功
OK
127.0.0.1:6379> get k3 # 之前 k3 是 123 , 现在变成 789 , 证明 xx 创建成功
"789"

1.2 get

语法 : get key
我们根据指定的 key 就可以获取到 value 的值

127.0.0.1:6379> set k1 123 # 设置键值对
OK
127.0.0.1:6379> get k1 # 获取键值对
"123"

对于 get 来说 , 只支持字符串类型的 value , 如果 value 是其他类型 , 查询就会失败

127.0.0.1:6379> lpush k5 11 22 33 # k5 是 list 类型
(integer) 3
127.0.0.1:6379> get k5 # value 是其他类型 , get 就会失败
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> type k5 # 我们也可以通过 type 查看 k5 的类型
list

1.3 mset、mget

mset 和 mget 可以一次操作多组键值对

一次网络通信传输就可以进行多组操作

image.png
语法 :
mset key1 value1 [key2 value2 …]
mget key1 [key2 …]

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 设置多组键值对
OK
127.0.0.1:6379> mget k1 k2 k3 # 获取多组键值对
1) "v1"
2) "v2"
3) "v3"

那 mset 和 mget 的时间复杂度为 O(N)

此处的 N 不是整个 Redis 服务器中所有的 key 的数量 , 而是当前命令中给出的 key 的数量 , 那我们也可以变相的认为他的时间复杂度为 O(1)

1.4 setnx、setex、psetex

setnx : 不存在才去设置 , 存在的话就会设置失败

127.0.0.1:6379> setnx k1 v1 # setnx 指的是不存在才去设置
(integer) 1
127.0.0.1:6379> get k1 # 获取 k1 
"v1"
127.0.0.1:6379> setnx k1 other # 此时 k1 已经存在, setnx 再去设置 k1 就会失败
(integer) 0
127.0.0.1:6379> get k1 # 获取到的还是之前的值
"v1"

setex : 设置超时时间 , 单位为 s
语法 : setex key seconds value

127.0.0.1:6379> setex k2 10 v2 # 设置超时时间(单位: s)
OK
127.0.0.1:6379> ttl k2
(integer) 5
127.0.0.1:6379> ttl k2
(integer) -2

psetex : 也是设置超时时间 , 单位是 ms
语法 : psetex key milliseconds value

127.0.0.1:6379> psetex k3 100 v3 # 设置超时时间(单位: ms)
OK
127.0.0.1:6379> ttl k3
(integer) -2

1.5 incr、incrby

这一组命令 , 实际上操作的是数字
incr 表示针对 value + 1
incrby 表示针对 value + n
incrbyfloat 表示针对 value +/- 小数
decr 表示针对 value - 1
decrby 表示针对 value - n

我们分别来看
incr 语法 : incr key , 返回值就是 +1 之后的值

要求 key 对应的 value 必须要是整数

127.0.0.1:6379> set k1 10 # 设置键值对, 要求 value 为数值
OK
127.0.0.1:6379> incr k1 # 对 k1 进行自增
(integer) 11 # 返回值代表 +1 之后的数
127.0.0.1:6379> get k1 
"11"
127.0.0.1:6379> set k2 hello # 设置键值对, 但是 value 设置成字符串类型
OK
127.0.0.1:6379> incr k2 # 对字符串进行自增操作就会失败
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k3 1.5 # 对小数进行 incr 操作也会失败
OK
127.0.0.1:6379> incr k3
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k4 999999999999999999999999999999999999999999999999999999 # 对一个非常大的数进行自增操作也会失败
OK
127.0.0.1:6379> incr k4
(error) ERR value is not an integer or out of range

那如果我们操作的 key 不存在 , 会怎样处理

127.0.0.1:6379> incr k5
(integer) 1 # 返回值代表 +1 之后的数
127.0.0.1:6379> get k5 # 返回值为 1 代表之前的数是 0
"1"

这也就是说 , incr 操作的 key 如果不存在 , 就会把这个 key 的 value 当做 0 来使用

incrby : incrby 可以对 key 进行 +n 的操作
语法 : incrby key increment

127.0.0.1:6379> set k6 10 # 设置键值对, 要求 value 为数值
OK
127.0.0.1:6379> incrby k6 100 # 对 k6 进行 +100 的操作
(integer) 110 # 返回值代表 +n 之后的结果
127.0.0.1:6379> get k6
"110"
127.0.0.1:6379> set k7 hello # 设置键值对, 但是 value 设置成字符串类型
OK
127.0.0.1:6379> incrby k7 100 # 对字符串进行 incrby 操作就会失效
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k8 3.14 # 设置键值对, 但是 value 设置成浮点数类型
OK
127.0.0.1:6379> incrby k8 100 # 对小数进行 incrby 操作就会失效
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k9 99999999999999999999999999999999999999999999999999999999999999 # 对一个非常大的数进行自增操作也会失败
OK
127.0.0.1:6379> incrby k9 100 
(error) ERR value is not an integer or out of range

127.0.0.1:6379> incrby k10 100 # 对一个不存在的 key 进行 incrby 操作, 他会从 0 开始 +n
(integer) 100
127.0.0.1:6379> get k10
"100"

那 incrby 加上一个负数 , 就相当于减法了

但是没人这样用 , 大家都直接使用 decr / decrby 这个命令了

127.0.0.1:6379> set k6 10 # 设置键值对, 要求 value 为数值
OK
127.0.0.1:6379> incrby k6 -1 # n 设置成负数就代表减法
(integer) 109

1.6 decr、decrby、incrbyfloat

decr 就是把 key 对应的 value 进行 -1 操作

decr 跟 incr 的要求相同

  1. key 对应的 value 必须是整数
  2. 如果这个 key 对应的 value 不存在 , 则当做 0 来处理
127.0.0.1:6379> set k1 21 # 设置键值对, 要求 value 为数值
OK
127.0.0.1:6379> decr k1 # -1 操作
(integer) 20 # 返回值同样是 -1 之后的结果
127.0.0.1:6379> set k2 hello # 设置键值对, 但是 value 设置成字符串类型
OK
127.0.0.1:6379> decr k2 # 对字符串进行 incrby 操作就会失效
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k3 9999999999999999999999999999999999999999999999999999  # 对一个非常大的数进行自减操作也会失败
OK
127.0.0.1:6379> decr k3
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set k4 1.5 # 设置键值对, 但是 value 设置成浮点数类型
OK
127.0.0.1:6379> decr k4 # 对小数进行 incrby 操作就会失效
(error) ERR value is not an integer or out of range
127.0.0.1:6379> decr k5 # 对一个不存在的 key 进行 decr 操作, 会把 key 视为 0
(integer) -1 # 返回值为 -1 就代表 key 原本是 0
127.0.0.1:6379> get k5
"-1"

decrby 就是把 key 对应的 value 进行 -n 的操作

127.0.0.1:6379> set k1 20 # 设置键值对, 要求 value 为数值
OK
127.0.0.1:6379> decrby k1 10 # 对 k1 进行 -n 操作
(integer) 10
127.0.0.1:6379> get k1 
"10"
127.0.0.1:6379> decrby k1 -10 # 如果填写的负数, 那就会认为是 +n 的效果
(integer) 20

incrbyfloat 是针对浮点数进行运算的

127.0.0.1:6379> set k1 10.5 # 设置键值对, 要求 value 为浮点数
OK
127.0.0.1:6379> incrbyfloat k1 0.5 # 对 k1 + 0.5
"11"
127.0.0.1:6379> incrbyfloat k1 -0.5 # 对 k1 - 0.5
"10.5"

那 incrbyfloat 是没有对应的 decrbyfloat 这样对应的操作的 , 我们只能将操作数修改成负数来达到减法的效果


上面的这五个操作 , 他们的时间复杂度都是 O(1) 的
另外 , 由于 Redis 处理命令的时候 , 是单线程的模型 , 那多个客户端同时针对同一个 key 进行 incr 操作 , 也就不会引起所谓的 “线程安全” 问题

1.7 append

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

字符串的拼接 : append
获取字符串的部分内容 : getrange
修改字符串的部分内容 : setrange
获取字符串的长度 : strlen

那我们先来看 append , 如果 key 已经存在并且 value 是一个 string 类型 , 那就会将 value 追加到原来的 string 的后面 ; 如果 key 不存在 , 则效果等同于 set 命令 , 也就是直接创建出一个新的键值对对象
语法 : append key value
他的时间复杂度也是 O(1) , 返回值代表追加完成之后 string 的长度

127.0.0.1:6379> set k1 hello # 设置键值对
OK
127.0.0.1:6379> append k1 world # 追加字符串
(integer) 10 # 返回值代表追加完成之后 string 的长度
127.0.0.1:6379> get k1 # 我们可以看到, 字符串已经被追加
"helloworld"
127.0.0.1:6379> append k2 hahaha # 如果要追加的 key 不存在, 则是创建出一个新的键值对
(integer) 6
127.0.0.1:6379> get k2
"hahaha"

那如果我们追加一个中文呢 ? 返回值是多少 ?

127.0.0.1:6379> append k3 你好
(integer) 6

我们可以看到 , 返回值为 6 , 要注意 : append 返回值的长度的单位是字节

Redis 的字符串不会对字符编码做任何处理 , 也就是说 Redis 不认识字符 , 只认识字节

那为什么会打印 6 呢 ?
这是因为我们使用的 SSH 终端 , 默认的是 UTF8 编码 , 在终端输入汉字之后 , 也就是按照 UTF8 编码的 , 那一个汉字在 UTF8 字符集中 , 通常是 3 个字节的 .
那刚才也说了 , 我们 Redis 不会对字符编码做任何处理 , 那我们看看获取一下 k3 是什么样子的

127.0.0.1:6379> get k3
"\xe4\xbd\xa0\xe5\xa5\xbd"

\xe4\xbd\xa0\xe5\xa5\xbd 就是十六进制的 “你好”

我们可以在启动 Redis 客户端的时候 , 加上一个 --raw 这样的选项 , 就可以使 Redis 客户端能够自动的把二进制数据尝试翻译

那我们就可以重新启动客户端
先按 Ctrl + D 退出 Redis 客户端

不要按到 Ctrl + S , Ctrl + S 是 XShell 的一个特色功能 , 是用来锁定当前屏幕的 , 我们可以通过 Ctrl + Q 取消锁定

然后输入 redis-cli --raw 重新启动客户端
image.png

1.8 getrange

getrange 的作用是获取字符串的子串 , 也就是 Java 中的 substring
语法 : getrange key start end , 其中 start 和 end 是左闭右闭的
另外 , Redis 的下标支持负数 , 比如 -1 就代表倒数第一个元素

127.0.0.1:6379> set k1 helloworld
OK
127.0.0.1:6379> getrange k1 0 -1 # 第一个元素~最后一个元素
helloworld
127.0.0.1:6379> getrange k1 1 -2 # 第二个元素~倒数第二个元素
elloworl

那我们要是切除中文呢

127.0.0.1:6379> getrange k2 0 -1 # 第一个字符~最后一个字符 就相当于获取所有字符, 没啥问题
你好
127.0.0.1:6379> getrange k2 1 -2 # 但是如果进行切割, 那切除的结果在 utf8 码表上不知道能查出一些什么
���

1.9 setrange

setrange 的作用就是修改字符串的一部分
语法 : setrange key offset value
其中 , offset 代表偏移量 , 指的是从第几个字符开始进行替换
那什么时候结束 , 不需要我们考虑 , 这是根据 value 的长度自动判断的
返回值就代表替换之后新的字符串的长度

127.0.0.1:6379> set k1 helloworld
OK
127.0.0.1:6379> setrange k1 1 aaa # 从 1 开始, 修改成 aaa
10 # 返回值就代表替换之后新的字符串的长度
127.0.0.1:6379> get k1
haaaoworld
127.0.0.1:6379> setrange k1 1 bbbbbbb # 从 1 号位置开始, 修改成 bbbbbbb
10
127.0.0.1:6379> get k1
hbbbbbbbld
127.0.0.1:6379> setrange k1 1 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb # 如果修改的 value 过长也会影响总长度
55
127.0.0.1:6379> get k1
hbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

如果当前咱们 value 是一个中文字符串 , 进行 setrange 的时候 , 是有可能出现问题的

127.0.0.1:6379> set k2 你好世界
OK
127.0.0.1:6379> setrange k2 1 111111
12
127.0.0.1:6379> get k2
�111111��界

如果我们针对一个不存在的 key 进行替换操作 , 会产生什么样的效果呢 ?

127.0.0.1:6379> setrange k4 1 hahaha # 从 1 号位置开始修改不存在的字符串
7 # 六个字符返回值为 7?
127.0.0.1:6379> get k4
hahaha

那我们的 hahaha 是六个字节 , 但是范围值却变成了 7 , 这是怎么回事 ?
这是因为我们设置的是从第一个元素开始进行 , 那 Redis 的实现的策略是在前面凭空生成了一个字节 , 这个字节里面的内容就是 0x00 .

1.10 strlen

strlen 的作用就是获取到字符串的长度 , 单位是字节 . 当 key 对应的 value 存储的不是 string 的时候就会报错

127.0.0.1:6379> set k1 helloworld
OK
127.0.0.1:6379> strlen k1 # 获取字符个数
10
127.0.0.1:6379> set k2 你好 
OK
127.0.0.1:6379> strlen k2 # 一个汉字三个字节
6
127.0.0.1:6379> strlen k3 # 获取不存在的 key 就会返回 0
0
127.0.0.1:6379> lpush k4 111 222 333
3
127.0.0.1:6379> strlen k4 # 获取其他类型就会报错
WRONGTYPE Operation against a key holding the wrong kind of value

小结

在这里插入图片描述

二 . string 的编码方式

字符串的内部编码有三种 :

  1. int : 保存整数 , 内部是 64 位 / 8 字节 的整数
  2. embstr : 保存比较短的字符串
  3. raw : 保存比较长的字符串

我们可以通过 object encoding 命令查看当前数据的编码方式

127.0.0.1:6379> set k1 123 # 设置整数类型的字符串
OK
127.0.0.1:6379> object encoding k1 # 查看 value 的编码方式
"int"
127.0.0.1:6379> set k2 hello # 设置字符串类型的字符串(比较短的)
OK
127.0.0.1:6379> object encoding k2 # 查看 value 的编码方式
"embstr"
127.0.0.1:6379> set k3 qwertyuiopasdfghjklzxcvbnmqertyuiopasdfghjklzcvbnm # 设置字符串类型的字符串(比较长的)
OK
127.0.0.1:6379> object encoding k3 # 查看 value 的编码方式
"raw"

那如果我们存入一个小数呢 , 类型是什么 ?

127.0.0.1:6379> set k4 3.14 # 存储一个小数
OK
127.0.0.1:6379> object encoding k4 
"embstr" # 我们可以看到编码方式为 embstr

Redis 存储小数是使用字符串来存储的 , 这也意味着每次进行算术运算 , 都需要把字符串先转化成小数进行运算 , 然后再将结果转化回字符串

三 . 应用场景

3.1 缓存

Redis 作为缓存.png

3.2 计数器

Redis 作为计数器.png

实际中要开发⼀个成熟、稳定的真实计数系统 , 要面临的挑战不是这么简单的 , 我们还需要考虑防作弊、按
照不同维度计数、避免单点问题、数据持久化等等

避免单点问题指的是不能只考虑当前主机的数据库 , 也要考虑分布式系统中其他主机的数据

3.3 共享会话

我们先看这种情况
image.png
如果每个应用服务器都维护自己的会话数据 , 此时各个应用服务器之间数据不共享 , 用户请求访问到不同的服务器上就可能出现一些不能正确登录的情况了
那更合理的做法就是将会话单独保存到 Redis 中 , 任何服务器要获取用户的登录状态都需要到 Redis 中获取
image.png

3.4 手机验证码

一般手机验证码的流程是这样的

  1. 生成验证码 : 用户输入手机号 , 然后点击获取验证码

但是一般会限制点击获取验证码 , 比如 1min 以内最多获取 5 次验证码 或者 每次获取验证码必须间隔 30s

  1. 检查验证码 : 把短信收到的验证码提交到系统中 , 由系统来去验证是否正确

我们可以用伪代码来理解这个问题

// phoneNumber 相当于用户的手机号
String 发送验证码 (phoneNumber) {
    key = "shortMsg:limit:" + phoneNumber;

    // 设置过期时间为 1 分钟 (60 秒)
    // 使⽤ NX, 只在不存在 key 时才能设置成功
    boolean r = Redis 执行命令: set key 1 ex 60 nx // 1 代表第一次发送
    // 设置失败 -> 代表用户之前操作过验证码
    if (r == false) {
        // 查看一下目前已经发送的次数
        // incr 返回值是用户发送验证码的次数
        long c = Redis 执⾏命令: incr key // 发送失败代表用户又发了一次验证码, 所以要 +1
        if (c > 5) {
            // 说明超过了⼀分钟 5 次的限制了
            // 限制发送
            return null;
        }
    }

    // 说明要么之前没有设置过⼿机的验证码
    // 要么次数没有超过 5 次
    String validationCode = ⽣成随机的 6 位数的验证码 ();
    validationKey = "validation:" + phoneNumber;// 编写验证码的前缀
    // 验证码 5 分钟 (300 秒) 内有效
    Redis 执⾏命令: set validationKey validationCode ex 300;// 将验证码存入到 Redis 中
    // 返回验证码, 随后通过手机短信发送给⽤⼾
    return validationCode;
}

// 验证用户输⼊的验证码是否正确
// phoneNumber 代表手机号
// validationCode 代表用户输入的验证码
boolean 验证验证码 (phoneNumber, validationCode) {
    // 根据手机号构造出 Redis 中存储的 key
    validationKey = "validation:" + phoneNumber;

    // 去 Redis 中查询该电话号是否存在验证码
    String value = Redis 执⾏命令:get validationKey;

    // 验证码不存在
    if (value == null) {
        // 验证失败
        return false;
    }

    // 验证码存在
    // 判断 Redis 中存储的验证码和用户输入的验证码是否相同
    if (value == validationCode) {
        return true;
    } else {
        return false;
    }
}

对于 Redis 中的 string 数据类型 , 已经讲解完毕
如果对你有帮助的话 , 还请一键三连~

在这里插入图片描述

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

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

相关文章

# 利刃出鞘_Tomcat 核心原理解析(十一)-- Tomcat 附加功能 WebSocket -- 2

利刃出鞘_Tomcat 核心原理解析(十一)-- Tomcat 附加功能 WebSocket – 2 一、Tomcat专题 - WebSocket - 案例 - 登录功能 1、在项目 dzs168_chat_room 中,导入 tomcat 项目依赖( dzs168_chat_room/web/lib/ ) idea -…

花生壳的登录及获取二级域名

1、下载花生壳客户端 2、安装完毕 3、扫码登录 4、微信登录花生壳管理后台 5、二级域名的注册 已经帮我们自动生成了一个免费的二级域名。 我们可以用这个二级域名快速的建立网站了。

[YM]课设-C#-WebApi-Vue-员工管理系统 (七)员工统计表

前端: 注:这里主要解释下echarts组件,需要一定的Vue基础 emmmmm 明显能看到上面写“对不起暂未开发” 是的 这个是博主自己加上去的 but 这个统计表也是类似于Element UI的小组件 Element:Element - 网站快速成型工具 &am…

Quartz.Net_依赖注入

简述 有时会遇到需要在IJob实现类中依赖注入其他类或接口的情况,但Quartz的默认JobFactory并不能识别具有有参构造函数的IJob实现类,也就无法进行依赖注入 需要被依赖注入的类: public class TestClass {public TestClass(Type jobType, s…

Python 从入门到实战5(列表的其它操作)

我们的目标是:通过这一套资料学习下来,通过熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。 之前的文章我们通过举例学习了python 中列表的简单操作&#xff0…

虚拟机输入ip addr不显示IP地址

本机配置 Window10 VMware Workstation 17 CentOS 7 虚拟机输入ip addr查询不到ip地址(下图) 解决办法: 查看配置文件,输入下面命令(用于编辑文件) vi /etc/sysconfig/network-scripts/ifcfg-ens33进入配置配置文件&#xf…

交叉编译 gmp

文章目录 交叉编译 gmp1 概述2 源码下载2.1 官网下载2.2 使用 apt source 下载 3 交叉编译4 关于 DESTDIR 的说明 交叉编译 gmp 1 概述 GMP (GNU Multiple Precision Arithmetic Library) 是一个用于任意精度计算设计的数学库,它的主要目标应用是密码学应用和研究…

ARP协议和DNS的工作原理

ARP协议 ARP协议的工作原理: 首先主机向自己的网络广播发送一个arp请求,请求报文包括目的端的ip地址和目的端的以太网地址。网络上的其他机器收到这个请求,但只有被请求的才会回应一个应答报文,报文中有自己的物理地址。 arp维护了…

【python因果推断库1】协方差分析(ANCOVA)用于处理前/后非等效组设计

目录 生成合成数据 分析 这是一个基于合成数据的初步示例。希望不久之后能用真实研究的数据进行更新。 在只有一次预处理测量和一次后处理测量的情况下,我们可以使用类似于协方差分析(ANCOVA)的方法来分析非等效组设计(NEGD)实验的数据。基本模型是: i指…

Vue(五). 安装脚手架及一些基本配置

文章目录 vue脚手架前言1. 安装脚手架1. 安装nvm2. 使用nvm安装node3. 配置node的全局路径和缓存路径4. 配置npm默认镜像源5. 安装脚手架全局路径和缓存测试 2. 文件结构及项目配置2.1 文件结构2.2 项目基本配置补充. vue项目安装依赖的一个问题 vue脚手架前言 脚手架也叫Vue …

敏捷需求管理,推动敏捷项目成功——Leangoo领歌敏捷工具

在敏捷项目管理中,需求管理是决定项目成功的关键环节。准确捕捉和高效管理需求,不仅能避免项目偏航,还能确保最终交付的产品与客户预期高度契合。Leangoo领歌敏捷工具,正是为此而生,助力团队轻松实现需求管理的每一步。…

vue中使用原生的video播放flv和mp4格式的视频

安装 npm i flv.js html <video v-if"videoId"controls id"videoElement"preload"metadata"controlslist"nodownload noremoteplayback" ><source :type"video/${videoType}" />您的浏览器不支持HTML5视频播…

Ansible一键安装Harbor服务

环境说明 企业内网环境,使用docker-compose的方式安装Harbor服务,需要先安装docker、docker-compose两个服务,将以二进制的方式安装docker和docker-compose,以适配各种安装环境。 docker版本:20.10.21,建议使用20.10以上的版本,低版本的会出现安装异常;Docker-compose版…

记一次ssh伪终端修改为shell

问题 用户ssh进行连接后&#xff0c;默认为伪终端。 解决办法&#xff0c;可以先拿到终端shell&#xff0c;查看用户是否为/bin/bash&#xff1a; 不是/bin/bash&#xff0c;使用如下命令进行修改&#xff1a; chsh -s /bin/bash rootservice sshd restart

在繁忙工作环境中提升开发效率:JetBrains IntelliJ IDEA 的应用

目录 前言1. IntelliJ IDEA 的核心功能1.1 智能代码补全&#xff1a;提升编码效率的利器1.2 深度代码分析&#xff1a;防患于未然1.3 代码重构&#xff1a;保持代码整洁有序 2. 提升团队协作与项目管理2.1 集成版本控制&#xff1a;高效的团队协作2.2 内置任务管理&#xff1a;…

开店到经营,分贝通帮助连锁经营企业这样省钱

如果说大企业的经营核心是做好主营业务的大生意,那么对于连锁经营企业而言,线下门店的一个个小生意,其实也隐藏着“大学问”。费用支出方面,如何从细节处节流,让资金流呈现更良性循环,是连锁经营行业的重要课题。 1、开店前:选址BD全国跑,筐筐发票财务恼 2、日常经营:费用类目…

Qt:玩转QPainter后转之时钟

前言 简单了解了QPainter之后当然是要找两个例子练练手啦。 正文 先看效果图 在绘制之前我们要先构思好自己要绘制的对象可以分成几部分&#xff0c;比如我要绘制时钟的话&#xff0c;我可以分成&#xff1a;外边框(圆环或者圆)&#xff0c;圆形背景&#xff0c;刻度&…

MySQL 使用C语言链接

mysql的基础&#xff0c;我们之前已经学过&#xff0c;后面我们只关心使用 要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作&#xff1a; 保证mysql服务有…

【WPF】WPF学习之【二】布局学习

WPF布局学习 常用布局Grid网格布局StackPanel 布局CanvasDockPanel布局WrapPanel布局 常用布局 1、StackPanel: 学习如何使用StackPanel进行垂直和水平布局。 2、Grid: 掌握Grid的网格布局技术。 3、Canvas: 了解Canvas的绝对定位布局。 4、DockPanel: 学习DockPanel的停靠…

【加密社】马后炮视角来看以太坊二层战略

阅读正文前先给大家普及下知识&#xff0c;以下文章中提到的 Blobs指的是&#xff1a;"Blob Carriers" 或 "Calldata Blobs" 这是在以太坊网络中用于携带数据的一种方式&#xff0c;尤其是在涉及Rollup&#xff08;如Optimistic Rollup和ZK-Rollup&#xf…