美文网首页
redis字符串对象

redis字符串对象

作者: 快点给我想个名 | 来源:发表于2019-11-27 22:03 被阅读0次

    内容来自:
    《redis设计与实现》购买本书请访问: 京东商城
    《Redis 深度历险:核心原理与应用实践》购买本书请访问: 京东商城

    字符串对象的编码可以是 intraw 或者 embstr

    • int
      如果一个字符串对象保存的是整数值, 并且这个整数值可以用 long 类型来表示, 那么字符串对象会将整数值保存在字符串对象结构的 ptr属性里面(将 void* 转换成 long ),并将字符串对象的编码设置为 int
    int编码的字符串对象
    • raw
      如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度大于 39 字节, 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值, 并将对象的编码设置为 raw
    raw编码的字符串
    • embstr
      如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度小于等于 39 字节, 那么字符串对象将使用 embstr 编码的方式来保存这个字符串值
    embstr编码的字符串
    • 编码转换

      • 对于 int 编码的字符串对象来说, 如果我们向对象执行了一些命令, 使得这个对象保存的不再是整数值, 而是一个字符串值, 那么字符串对象的编码将从 int 变为 raw
      • Redis 没有为 embstr 编码的字符串对象编写任何相应的修改程序 (只有 int 编码的字符串对象和 raw 编码的字符串对象有这些程序), 所以 embstr 编码的字符串对象实际上是只读的: 当我们对 embstr 编码的字符串对象执行任何修改命令时, 程序会先将对象的编码从 embstr 转换成 raw , 然后再执行修改命令; 因为这个原因, embstr 编码的字符串对象在执行修改命令之后, 总会变成一个 raw 编码的字符串对象
    • 注意

      • 一个浮点数到字符串对象里面, 那么程序会先将这个浮点数转换成字符串值, 然后再保存起转换所得的字符串值
      • embstr存储形式是这样一种存储形式,它将 RedisObject对象头和 SDS对象连续存在一起,使用malloc方法一次分配。而raw存储形式不一样,它需要两次malloc,两个对象头在内存地址上一般是不连续的
    • 为什么字符串值的长度大于 39 字节就会从embstr 转为raw
      首先内存分配器 jemalloc/tcmalloc 等分配内存大小的单位都是 2、4、8、16、32、64 等,为了能容纳一个完整的embstr对象,jemalloc最少会分配 32 字节的空间,如果字符串再稍微长一点,那就是 64 字节的空间。如果总体超出了64字节,Redis 认为它是一个大字符串,不再使用 emdstr形式存储,而该用 raw 形式。当内存分配了64字节空间后,看下面分析:
      RedisObject对象type4bit,encoding4bit,lru24bit,refcount4字节,*ptr8字节,这样一个RedisObject就占用16字节的空间。而SDS对象中len4字节,free4字节,buf假设为空。这样分配一个字符串最小占用空间为24字节(16+8),但是别忘了字符串又是以\0结尾占1字节。所以embstr 最大容纳长度是39(64-24-1)字节。

    • 字符串命令部分实现

      命令 int 编码的实现方法 embstr 编码的实现方法 raw 编码的实现方法
      SET 使用 int 编码保存值。 使用 embstr 编码保存值。 使用 raw 编码保存值。
      GET 拷贝对象所保存的整数值, 将这个拷贝转换成字符串值, 然后向客户端返回这个字符串值。 直接向客户端返回字符串值。 直接向客户端返回字符串值。
      APPEND 将对象转换成 raw 编码, 然后按 raw 编码的方式执行此操作。 将对象转换成 raw 编码, 然后按 raw 编码的方式执行此操作。 调用 sdscatlen 函数, 将给定字符串追加到现有字符串的末尾。
      INCRBYFLOAT 取出整数值并将其转换成 longdouble 类型的浮点数, 对这个浮点数进行加法计算, 然后将得出的浮点数结果保存起来。 取出字符串值并尝试将其转换成long double 类型的浮点数, 对这个浮点数进行加法计算, 然后将得出的浮点数结果保存起来。 如果字符串值不能被转换成浮点数, 那么向客户端返回一个错误。 取出字符串值并尝试将其转换成 longdouble 类型的浮点数, 对这个浮点数进行加法计算, 然后将得出的浮点数结果保存起来。 如果字符串值不能被转换成浮点数, 那么向客户端返回一个错误。
      INCRBY 对整数值进行加法计算, 得出的计算结果会作为整数被保存起来。 embstr 编码不能执行此命令, 向客户端返回一个错误。 raw 编码不能执行此命令, 向客户端返回一个错误。
      DECRBY 对整数值进行减法计算, 得出的计算结果会作为整数被保存起来。 embstr 编码不能执行此命令, 向客户端返回一个错误。 raw 编码不能执行此命令, 向客户端返回一个错误。
      STRLEN 拷贝对象所保存的整数值, 将这个拷贝转换成字符串值, 计算并返回这个字符串值的长度。 调用 sdslen 函数, 返回字符串的长度。 调用 sdslen 函数, 返回字符串的长度。
      SETRANGE 将对象转换成 raw 编码, 然后按 raw 编码的方式执行此命令。 将对象转换成 raw 编码, 然后按 raw 编码的方式执行此命令。 将字符串特定索引上的值设置为给定的字符。
      GETRANGE 拷贝对象所保存的整数值, 将这个拷贝转换成字符串值, 然后取出并返回字符串指定索引上的字符。 直接取出并返回字符串指定索引上的字符。 直接取出并返回字符串指定索引上的字符。

    相关文章

      网友评论

          本文标题:redis字符串对象

          本文链接:https://www.haomeiwen.com/subject/hdwmwctx.html