目录
[String 类型基本概念](#String 类型基本概念)
[SET & GET](#SET & GET)
[SET 命令](#SET 命令)
[GET 命令](#GET 命令)
[MSET & MGET](#MSET & MGET)
[MSET 命令](#MSET 命令)
[MGET 命令](#MGET 命令)
[SETNX & SETEX & PSETEX](#SETNX & SETEX & PSETEX)
[SETNX 命令](#SETNX 命令)
[SETEX 命令](#SETEX 命令)
[PSETEX 命令](#PSETEX 命令)
[INCR 命令](#INCR 命令)
[INCRBY 命令](#INCRBY 命令)
[DECR 命令](#DECR 命令)
[DECRBY 命令](#DECRBY 命令)
[INCRBYFLOAT 命令](#INCRBYFLOAT 命令)
[APPEND 命令](#APPEND 命令)
[GETRANGE 命令](#GETRANGE 命令)
[SETRANGE 命令](#SETRANGE 命令)
[STRLEN 命令](#STRLEN 命令)
引言
- redis 中所有的 key 均为字符串,但 value 的类型却存在差异
redis 文档给出的语法格式说明:
- [ ] 相当于一个独立的单元表示可选项,即 可有可无
- | 表示 或者 的意思,多个之间仅能选择一个
- [ ] 和 [ ] 之间是可以同时存在的
快速清除 redis 中的所有键值对 :
- 该命令能够把 redis 上所有的键值对都带走
语法:
FLUSHALL
- 在公司中,尤其是生产环境的数据库,千万不要敲该命令!!
注意:
- 在操作 linux 的时候 千万不要乱按 ctrl + s
- ctrl + s 在 xshell 中的作用是 "冻结当前页面"
- 按 ctrl + q 即可解除冻结
String 类型基本概念
- Redis 中的字符串是以二进制数据的方式存储的,且它不会进行任何编码转换
- 这意味着你存的是什么,取出来就是什么
- 相比之下 MySQL 默认的字符集是拉丁文,如果你试图插入中文 而没有更改字符集,那么便会失败
- 所以 Redis 一般来说不会遇到乱码问题,因为 Redis 中没有字符集
- Redis 中可以存储各种类型的数据
- 包括 文本数据、整数、普通文本字符串、JSON、XML ,甚至二进制数据(如图片、视频、音频等)
- 但 Redis 对于 String 类型的大小限制为 512 M
注意:
- 由于 Redis 是单线程模型,且其设计目标是使得所有的操作都能快速完成
- 因此 存储大文件,如音频、视频,可能会影响 Redis 的性能
原因:
- 处理这些大文件需要更多的时间,这可能会阻塞其他操作,从而降低整体的性能
总结:
- 虽然 Redis 技术上可以存储 音频 和 视频文件,但由于其单线程的特性和对 String 类型的大小限制 ,通常不建议这样做
SET & GET
SET 命令
不设置 NX 和 XX 参数时:
- 如果 key 不存在则创建新的键值对
- 如果 key 存在 则让新 value 覆盖旧 value ,可能改变原 value 的数据类型,且原 key 的 ttl (生存时间)也将失效
语法:
set key value [expiration EX seconds|PX milliseconds] [NX|XX]
时间复杂度:
- O(1)
实例理解一
- set key value ex 5
- 相当于 set key value + expire key 5
实例理解二
- NX :如果 key 存在则不设置 并返回 nil,如果 key 不存在才设置
- XX :如果 key 不存在则不设置(返回 nil),如果 key 存在才设置(相当于更新 key 的 value)
GET 命令
- Redis 的 get 命令只能用于获取去存储为 字符串类型的值
语法:
get key
时间复杂度:
- O(1)
实例理解
- 此处我们尝试使用 get 命令获取一个列表值
- Redis 报错!
MSET & MGET
MSET 命令
- 用于一次设置多个键的值
- MSET 命令会用新值替换旧值
- 这是一个原子操作,所有键的值都会同时设置
语法:
mset key value [key value ...]
时间复杂度:
- O(N)
- 其中 N 为设置 key value 键值对的个数,一般不会很大,也可认为是 O(1)
实例理解
- 此处我们一次性设置三个键值对
注意:
- 当一次性设置 10W 个键值对时,Redis 很有会被阻塞
MGET 命令
- 用于获取多个键的值
语法:
mget key [key ...]
时间复杂度:
- O(N)
- 其中 N 为获取 key 的个数,一般不会很大,也可认为是 O(1)
实例理解
- 此处我们一次性获取三个 key 所对应的 value 值
一次操作多组键值对 相较于 一次操作一组键值对
优势:
- 一次操作多组键值对可以减少网络延迟
- MSET 命令是原子的,要么所有键值对设置成功,要么所有键值对设置失败,确保了数据的一致性
- MSET 和 MGET 可以使代码更简洁,更易于理解和维护
SETNX & SETEX & PSETEX
SETNX 命令
- 等价于 set key value nx
- 即 key 不存在才能设置,key 存在则不设置 且返回 nil
语法:
setnx key value
实例理解
SETEX 命令
- 设置 key 的过期时间,时间单位为 秒
语法:
setex key seconds value
实例理解
PSETEX 命令
- 设置 key 的过期时间,时间单位为 毫秒
语法:
psetex key milliseconds value
实例理解
总结:
- 上述命令是针对 set 一些常见用法的缩写
- 之所以这样,是为了让操作更符合人的直觉,即使用者的门槛就越低,要背的东西就越少
注意:
- 在编程语言中 很多关键词 都是和自然语言相关的
- 所以后续我们去设置一些库、一些工具、一段代码给别人使用的时候,也要尽量符合直觉
- 不要设计的 反人类、反直觉
计数命令
INCR 命令
- 针对 key 对应的 value 进行一个 +1 操作
语法:
incr key
- key 对应的 value 必须为整数
- 此处为 64位 ------> 8字节的整数,相当于 Java 中的 long,表示的范围还是比较大的
时间复杂度:
- O(1)
返回值:
- 此操作的返回值,为 value +1 后的值
实例理解
注意:
- incr 操作的 key 如果不存在,就会把这个 key 的 value 当作 0 来使用
INCRBY 命令
- 针对 key 对应的 value 进行一个 +n 操作
语法:
incrby key increment
- key 对应的 value 必须为整数
时间复杂度:
- O(1)
返回值:
- 此操作的返回值,为 value +n 后的值
实例理解
- 此处我们针对 key 的 value 加 10
注意:
- incrby 操作的 key 如果不存在,就会把这个 key 的 value 当作 0 来使用
- incrby 命令也可针对 value 进行减法操作
DECR 命令
- 针对 key 对应的 value 进行一个 -1 操作
语法:
decr key
- key 对应的 value 必须为整数
时间复杂度:
- O(1)
返回值:
- 此操作的返回值,为 value -1 后的值
实例理解
注意:
- decr 操作的 key 如果不存在,就会把这个 key 的 value 当作 0 来使用
DECRBY 命令
- 针对 key 对应的 value 进行一个 -n 操作
语法:
decrby key decrement
- key 对应的 value 必须为整数
时间复杂度:
- O(1)
返回值:
- 此操作的返回值,为 value -n 后的值
实例理解
- 此处我们针对 key 的 value 减 10
注意:
- decrby 命令也可针对 value 进行加法操作
INCRBYFLOAT 命令
- 针对 key 对应的 value 进行 ± n 操作
语法:
incrbyfloat key increment
- key 对应的 value 可为****整型 或 浮点型
时间复杂度:
- O(1)
返回值:
- 此操作的返回值,为 value ± n 后的值
实例理解
- 此处我们针对 key 的 value 加 0.5
- 此处我们针对 key 的 value 减 0.5
- 只能用 加上负数的形式来实现减法
注意:
- 此处没有给 浮点型 提供减法版本的命令
- 因为使用 redis 进行的计数操作时,一般都是针对整数来进行的
总结
- 由于 redis 处理命令的时候为单线程模型
- 所以多个客户端同一时刻针对同一个 key 进行 incr 操作时,不会引起 线程安全问题
字符串操作命令
APPEND 命令
- 用于给将 给定值 追加到指定 key 的 value 的末尾
- 如果 key 存在并且是一个字符串,该命令会将 给定值 追加到原有的字符串后面
- 如果 key 不存在,则效果等同于 set 命令
语法:
append key value
时间复杂度:
- O(1)
返回值:
- 追加后的字符串长度,单位为字节
实例理解
- redis 不认字符,只认字节
- redis 不会对字符串的字符编码做任何处理
- 当前咱们 xshell 终端默认的编码方式为 UTF-8
- 所以当我们在终端中输入汉字后,将会以 UTF-8 进行汉字编码
- 一个汉字在 UTF-8 字符集中通常为 3 个字节
- 此处返回结果为 "你好" 这两个汉字的 UTF-8 编码
- 其中 '\x' 表示十六进制,"\xe4\xbd\xa0\xe5\xa5\xbd" 为转义字符
点击下方连接可进入 查询字符编码的网址
- 在启动 redis 客户端的时候,加上 --raw 这样的选项
- 便可使 redis 客户端 能自主翻译二进制数据
GETRANGE 命令
- 相当于 Java 中的 substring
- 超过范围的偏移量会根据 Sting 的长度调整成正确的值
语法:
getrange key start end
时间复杂度:
- O(N),这里的 N 为 start 到 end 之间的长度,一般不会很大,也可认为是 O(1)
返回值:
- 返回 key 对应的 string 的子串,由 start 和 end 确定(左闭右闭)
注意点一:
- 在 Redis 中指定的区间为闭区间
- 但 Java 中一般谈到区间 却大多为 左闭右开
- 且在整个编程大圈子中,区间也大多为左闭右开,但确实也有特殊情况,就比如此处的 Redis
注意点二:
- 正常下标都是从 0 开始的整数
- 但 Redis 支持负数下标 ,-1 代表倒数第一个元素,即下标为 len -1 的元素
实例理解
- 如果字符串中保存的是汉字,此时进行子串切分时很可能切出来的就不是完整的汉字了
- 如上图所示,强行切出 中间的四个字节
- 随便这么一切,切出的结果在 UTF-8 码表上便不知道查出的是什么字符了
注意:
- 在 Java 中不会存在上述情况
原因:
- Redis 中字符串的基本单位为 字节
- 但在 Java 中 字符串长度以 字符(char) 为单位,且 char 类型的数据占 2 字节
- Java 中字符(char)用的是 Unicode 编码,一个字符可以表示包括中文在内的各种符号
实例理解
基本概念
- 当编码方式为 UTF-8 时,一个汉字通常为 3 个字节
- 当编码方式为 Unicode 时,一个汉字通常为 2 个字节
重点理解
- Java 中字符串(String) 用的是 UTF-8 编码
- Java 标准库进行编码转换时,如从 Unicode 到 UTF-8,通常会抽象掉底层的细节,使得程序员一般感知不到编码方式的变换
补充:
- 在 MySQL 中 varchar(N) 类型数据中的 N 为字符数,这意味着无论字符是 英文 还是 中文 都只算一个字符
SETRANGE 命令
- 根据 偏移量(offset),从指定的字节开始进行 value 替换
语法:
setrange key offset value
时间复杂度:
- O(N),这里的 N 为 value 的长度,一般不会很大,也可认为是 O(1)
返回值:
- 替换之后新字符串的长度
实例理解
- setrange 针对不存在的 key 也是可以操作的,不过会把 offset 之前的内容填充为 0x00
- 如上图所示,凭空生产了一个字节,且该字节里面中内容为 0x00
- 此时的 value 值 aaa 便被追加到 0x00 后面了
注意:
- 如果当前的 value 为中文字符串,并 进行 setrange 命令的时候,是存在问题的
STRLEN 命令
- 用于获取 key 对应 value 的字符串长度
- 如果当前 key 对应的 value 不是字符串时,将会报错
语法:
strlen key
时间复杂度:
- O(1)
返回值:
- 获取到字符串的长度,单位是字节,当key 不存在时 返回 0
实例理解