目录

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内部具体是如何实现的,这是有变数的.一个数据结构可能对应多种编码方式,来应对不同场景下的业务.

通俗一点讲就是redis承诺这里有一个hash表,你进行查询,插入,删除操作,都保证时间复杂度是O(1),但是这个hash表背后的实现不一定就是标准的hash表,可能在特定的场景下会使用别的数据结构来实现,但是仍然保证时间复杂度是O(1).

redis的数据结构和内部编码

redis 字符串 带引号_redis 字符串 带引号_02

redis 字符串 带引号_redis 字符串 带引号_03

每种数据结构都至少有两种以上的内部编码实现,,同时有些内部编码可以做为多种数据结构的内部实现.

我们可以通过object encoding命令来查询其具体的内部编码.

redis这样设计的好处:

1.可以改进内部编码,而对外的数据结构和命令没有任何影响,这样一旦开发出来更优秀的内部编码,无需改动外部的数据结构和命令.

2.多种内部编码的实现可以在不同的场景下发挥各自的优势.例如 ziplist ⽐较节省内存,但是在列表元素⽐较多的情况下,性能会下降,这时候 Redis 会根据配置选项将列表类型的内部实现转换为 linkedlist,整个过程⽤⼾同样⽆感知。


Redis中的String类型

redis中所有的键的类型都是字符串类型,其他几种数据结构也都是在字符串类型的基础上构建的.

字符串类型实际的值,可以是字符串,包含一般格式的json,xml格式的字符串;也可以是数字,包含整数或者浮点数;也可以是二进制流数据,例如图片,音频等.但是一个字符串的最大值不能超过512MB.


由于 Redis 内部存储字符串完全是按照⼆进制流的形式保存的,所以 Redis 是不处理字符集


编码问题的,客⼾端传⼊的命令中使⽤的是什么字符集编码,就存储什么字符集编码。


String类型的常见命令

set

将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此 key 的 TTL 也全部失效。

redis 字符串 带引号_数据库_04

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

redis 字符串 带引号_redis 字符串 带引号_05

获取key对应的value.如果key不存在,返回nil.如果value的类型不是string会报错.

redis 字符串 带引号_redis 字符串 带引号_06

mget

一次性获取多个key的值.如果对应的key不存在或者对应的数据类型不是string则返回nil.

redis 字符串 带引号_缓存_07

时间复杂度是O(N),其中n是key的数量.

mset

一次性设置多个key的值.返回ok.时间复杂度是O(N),其中n是key的数量.

redis 字符串 带引号_数据库_08


String类型的计数命令

  • incr ,针对value+1
  • incrby,针对value+n
  • decr,针对value-1
  • decrby,针对value-n
  • incrbyfloat,针对value+/-小数
incr

redis 字符串 带引号_数据库_09


将 key 对应的 string 表⽰的数字加⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。



返回的是加完之后的数值.



incrby

redis 字符串 带引号_字符串_10


将 key 对应的 string 表⽰的数字加上对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。



decr




redis 字符串 带引号_数据库_11



将 key 对应的 string 表⽰的数字减⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。


incrbyfloat


将 key 对应的 string 表⽰的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的不是 string,则报错。允许采⽤科学计数法表⽰浮点数。


其他命令

append

redis 字符串 带引号_缓存_12


如果 key 已经存在并且是⼀个 string,命令会将 value 追加到原有 string 的后边。如果 key 不存在,则效果等同于 SET 命令。


时间复杂度:O(1)

返回值:追加完成之后string的长度.此处的单位是字节.

redis 字符串 带引号_缓存_13

redis的字符串不会对字符编码做任何处理,redis不认识字符只认识字节.

当前的xshell终端,是按照utf8的方式进行编码的,在终端输入汉字后,也是按照utf8进行编码的,一个汉字在utf8的字符集中,通常是3个字节的.

可以看到我们get key5得到的是你好的16进制的数据,对应的就是utf8中的你好.

如果不想得到数据而是汉字,可以在启动redis客户都安的时候加上--raw,此时redis客户端就能够自动的把二进制的数据尝试翻译.

redis 字符串 带引号_redis 字符串 带引号_14

getrange

redis 字符串 带引号_缓存_15


返回 key 对应的 string 的⼦串,由 start 和 end 确定(左闭右闭)。可以使⽤负数表⽰倒数。-1 代表倒数第⼀个字符,-2 代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的长度调整成正确的值。


redis 字符串 带引号_redis_16


如果value是汉字,此时切分出来的是什么就不确定了.


setrange


redis 字符串 带引号_redis_17


覆盖字符串的一部分,从指定的偏移开始.


返回的替换之后的string长度.


redis 字符串 带引号_数据库_18


redis 字符串 带引号_redis_19


针对汉字也可能会出现问题.


setrange针对不存在的key也可以操作,不过会把offset之前的内容填充为0x00.


strlen


获取key对应的string长度.当key存放的类型不是string时,会报错.



String类型的内部编码

String类型的内部编码有3种:

  • int:8个字节的长整型
  • embstr:小于等于39字节的字符串
  • raw:大于39字节的字符串.

redis会根据当前值的类型和长度动态决定使用哪种内部编码实现.

redis 字符串 带引号_redis 字符串 带引号_20

redis在存储小数的时候,本是上还是当作字符串来存储.意味着每次进行算数运算都需要把字符串转为小数.进行运算.结果在转为字符串.

redis 字符串 带引号_缓存_21