STRING
我们会经常打交道的string类型,在redis中拥有广泛的使用。也是开启redis数据类型的基础。
在我最最开始接触的redis的时候,总是以为字符串类型就是值的类型是字符串。
比如:SET key value
我的理解是value数据类型是stirng类型,现在来看呢,这句话说得不够具体全面。
所有的键都是字符串类型
字符串类型的值可以是字符串、数字、二进制
这里也就引出了,另一个概念:外部类型和内部类型
外部类型 vs 内部类型
这里的外部类型,就是我们所熟知的:字符串(string)、哈希(hash)、列表(list)、集合(set)、有序结合(zset)等
Q1:那么什么是内部类型呢?
Q2:外部类型和内部类型是什么时候出现的?
Q3:为什么要这样设计?
我们先来看问题1,可以这样理解,对外数据结构就像是我们的API,对外提供着一定组织结构的数据。
对内来说,我们可以更换里面的逻辑算法,甚至更换数据存储方式,比如将Mysql换成Redis.
内部类型其实就是数据存储的形式。举现在我们所讨论的stirng来说。
string的外部类型就是string,而它对应的数据内部存储结构分为三种。
int:8个字节的长整形 embstr:<=39个字节的字符串(3.2 版本变成了44) raw:>39个字节的字符串(3.2 版本变成了44)
所以,string类型会根据当前字符串的长度来决定到底使用哪种内部数据结构。
现在我们再回到问题上:什么是内部类型?
就是数据真正存储在内存上的数据结构。
其实第二个问题:外部类型和内部类型是什么时候出现的?
这里也算是有答案了,外部类型就是对外公开的数据类型也可以说是API,内部类型根据长度判断哪种内部结构。
第三个问题:为什么这样设计?
前后分离,如果有更好地内部数据类型,我们可以替换后面的数据类型,但不影响前面的Api. 还有一点也是根据不同情况,选择更好地数据结构,节省内存。毕竟是内存数据库,资源珍贵。
如何查看外部类型和内部类型
查看外部类型:type
127.0.0.1:6999[1]> SET sc sunchong // 对外类型:string OK 127.0.0.1:6999[1]> type sc string
127.0.0.1:6999[1]> HSET hsc sun chong // 对外类型:hash (integer) 1 127.0.0.1:6999[1]> type hsc hash
127.0.0.1:6999> RPUSH rsc s un ch hong (integer) 4 127.0.0.1:6999> TYPE rsc list
查看内部类型:object
int
127.0.0.1:6999[1]> set sc 1234567890123456789 // 对内类型:int OK 127.0.0.1:6999[1]> STRLEN sc (integer) 19 127.0.0.1:6999[1]> OBJECT encoding sc "int"
int -> embstr
(int 8位的长整形,最大存储十进制位数为19位)
127.0.0.1:6999[1]> set sc 12345678901234567890 // 对内类型:embstr OK 127.0.0.1:6999[1]> STRLEN sc (integer) 20 127.0.0.1:6999[1]> OBJECT encoding sc "embstr"
embstr -> raw
127.0.0.1:6999[1]> set sc 123456789012345678901234567890123456789 OK 127.0.0.1:6999[1]> STRLEN sc (integer) 39 127.0.0.1:6999[1]> OBJECT encoding sc "embstr"
127.0.0.1:6999[1]> set sc 12345678901234567890123456789012345678901 OK 127.0.0.1:6999[1]> STRLEN sc (integer) 41 127.0.0.1:6999[1]> OBJECT encoding sc "embstr"
额,这里我看《Redis 开发与运维》一书
39字节,embstr 转raw。写错了?
我的本机redis版本是5.0+,这本书是3.0,中间肯定是有了版本更新。
试试看看源码和提交记录 (https://github.com/antirez/redis/commit/f15df8ba5db09bdf4be58c53930799d82120cc34#diff-43278b647ec38f9faf284496e22a97d5)

继续尝试 embstr -> raw
127.0.0.1:6999[1]> set sc 12345678901234567890123456789012345678901234 OK 127.0.0.1:6999[1]> STRLEN sc (integer) 44 127.0.0.1:6999[1]> OBJECT encoding sc "embstr"
127.0.0.1:6999[1]> set sc 123456789012345678901234567890123456789012345 // 对内类型:raw OK 127.0.0.1:6999[1]> STRLEN sc (integer) 45 127.0.0.1:6999[1]> OBJECT encoding sc "raw"
常用命令
set key value [EX seconds] [PX milliseconds] [NX|XX]
-- ex 秒级过期时间
-- px 毫秒级过期时间
-- nx 不存在才能执行成功,类似添加
-- xx 必须存在才能执行成功,类似修改
nx
127.0.0.1:6999[1]> EXISTS bus (integer) 0 127.0.0.1:6999[1]> SET bus Q xx (nil) 127.0.0.1:6999[1]> SET bus Q nx OK
xx
127.0.0.1:6999[1]> EXISTS car (integer) 0 127.0.0.1:6999[1]> SET car B OK 127.0.0.1:6999[1]> SET car C nx (nil) 127.0.0.1:6999[1]> SET car C xx OK 127.0.0.1:6999[1]> GET car "C"
setnx / setxx
这两个命令会逐步弃用
String类型源码分析
SDS 数据结构
为什么Redis要自己实现一套简单的动态字符串?
1. 效率 2. 安全(二进制安全:C语言中的字符串已 “
