目录
Redis中的内部编码
redis的数据结构和内部编码
Redis中的String类型
String类型的常见命令
set
get
mget
mset
String类型的计数命令
incr
incrby
decr
incrbyfloat
其他命令
append
getrange
setrange
strlen
String类型的内部编码
Redis中的内部编码
redis中value的数据类型有多种,最通用的数据结构有String,List,set,hash和sorted set.
redis底层在实现上述数据结构的时候,会在源码层面,针对上述各个数据结构实现特定的优化,来达到节省空间/节省时间的效果.
也就是说每个数据结构在redis内部具体是如何实现的,这是有变数的.一个数据结构可能对应多种编码方式,来应对不同场景下的业务.
通俗一点讲就是redis承诺这里有一个hash表,你进行查询,插入,删除操作,都保证时间复杂度是O(1),但是这个hash表背后的实现不一定就是标准的hash表,可能在特定的场景下会使用别的数据结构来实现,但是仍然保证时间复杂度是O(1).
redis的数据结构和内部编码
每种数据结构都至少有两种以上的内部编码实现,,同时有些内部编码可以做为多种数据结构的内部实现.
我们可以通过object encoding命令来查询其具体的内部编码.
redis这样设计的好处:
1.可以改进内部编码,而对外的数据结构和命令没有任何影响,这样一旦开发出来更优秀的内部编码,无需改动外部的数据结构和命令.
2.多种内部编码的实现可以在不同的场景下发挥各自的优势.例如 ziplist ⽐较节省内存,但是在列表元素⽐较多的情况下,性能会下降,这时候 Redis 会根据配置选项将列表类型的内部实现转换为 linkedlist,整个过程⽤⼾同样⽆感知。
Redis中的String类型
redis中所有的键的类型都是字符串类型,其他几种数据结构也都是在字符串类型的基础上构建的.
字符串类型实际的值,可以是字符串,包含一般格式的json,xml格式的字符串;也可以是数字,包含整数或者浮点数;也可以是二进制流数据,例如图片,音频等.但是一个字符串的最大值不能超过512MB.
由于 Redis 内部存储字符串完全是按照⼆进制流的形式保存的,所以 Redis 是不处理字符集
编码问题的,客⼾端传⼊的命令中使⽤的是什么字符集编码,就存储什么字符集编码。
String类型的常见命令
set
将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此 key 的 TTL 也全部失效。
set命令支持多种选项来影响它的行为.
ex使用秒为单位设置key的过期时间.px使用毫秒作为单位设置key的过期时间.
nx表示如果key不存在才设置,key存在则不设置;xx表示如果key存在则设置,key不存在则不设置.
redis针对set的一些用法也延申出了一些命令.
setnx:key不存在才能设置,存在则设置失败.返回1表示设置成功,返回0表示没有设置.
setex:设置key的过期时间单位是秒.
psetex:设置key的过期时间单位是毫秒.
返回值:设置成功则返回ok,如果由于set指定了nx或者xx并且条件没有满足,set不会执行并返回nil.
get
获取key对应的value.如果key不存在,返回nil.如果value的类型不是string会报错.
mget
一次性获取多个key的值.如果对应的key不存在或者对应的数据类型不是string则返回nil.
时间复杂度是O(N),其中n是key的数量.
mset
一次性设置多个key的值.返回ok.时间复杂度是O(N),其中n是key的数量.
String类型的计数命令
- incr ,针对value+1
- incrby,针对value+n
- decr,针对value-1
- decrby,针对value-n
- incrbyfloat,针对value+/-小数
incr
将 key 对应的 string 表⽰的数字加⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。
返回的是加完之后的数值.
incrby
将 key 对应的 string 表⽰的数字加上对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。
decr
将 key 对应的 string 表⽰的数字减⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。
incrbyfloat
将 key 对应的 string 表⽰的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的不是 string,则报错。允许采⽤科学计数法表⽰浮点数。
其他命令
append
如果 key 已经存在并且是⼀个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在,则效果等同于 SET 命令。
时间复杂度:O(1)
返回值:追加完成之后string的长度.此处的单位是字节.
redis的字符串不会对字符编码做任何处理,redis不认识字符只认识字节.
当前的xshell终端,是按照utf8的方式进行编码的,在终端输入汉字后,也是按照utf8进行编码的,一个汉字在utf8的字符集中,通常是3个字节的.
可以看到我们get key5得到的是你好的16进制的数据,对应的就是utf8中的你好.
如果不想得到数据而是汉字,可以在启动redis客户都安的时候加上--raw,此时redis客户端就能够自动的把二进制的数据尝试翻译.
getrange
返回 key 对应的 string 的⼦串,由 start 和 end 确定(左闭右闭)。可以使⽤负数表⽰倒数。-1 代表倒数第⼀个字符,-2 代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的长度调整成正确的值。
如果value是汉字,此时切分出来的是什么就不确定了.
setrange
覆盖字符串的一部分,从指定的偏移开始.
返回的替换之后的string长度.
针对汉字也可能会出现问题.
setrange针对不存在的key也可以操作,不过会把offset之前的内容填充为0x00.
strlen
获取key对应的string长度.当key存放的类型不是string时,会报错.
String类型的内部编码
String类型的内部编码有3种:
- int:8个字节的长整型
- embstr:小于等于39字节的字符串
- raw:大于39字节的字符串.
redis会根据当前值的类型和长度动态决定使用哪种内部编码实现.
redis在存储小数的时候,本是上还是当作字符串来存储.意味着每次进行算数运算都需要把字符串转为小数.进行运算.结果在转为字符串.