使用Booksleeve处理Int64值

时间:2013-07-11 10:08:15

标签: redis booksleeve

我对Marc Gravell的Booksleeve库有疑问。

我试图理解书架如何处理Int64值(我实际上在Redis中有十亿的长值)

我使用反射来取消Set long值覆盖。

// BookSleeve.RedisMessage
protected static void WriteUnified(Stream stream, long value)
{
if (value >= 0L && value <= 99L)
{
    int i = (int)value;
    if (i <= 9)
    {
        stream.Write(RedisMessage.oneByteIntegerPrefix, 0, RedisMessage.oneByteIntegerPrefix.Length);
        stream.WriteByte((byte)(48 + i));
    }
    else
    {
        stream.Write(RedisMessage.twoByteIntegerPrefix, 0, RedisMessage.twoByteIntegerPrefix.Length);
        stream.WriteByte((byte)(48 + i / 10));
        stream.WriteByte((byte)(48 + i % 10));
    }
}
else
{
    byte[] bytes = Encoding.ASCII.GetBytes(value.ToString());
    stream.WriteByte(36);
    RedisMessage.WriteRaw(stream, (long)bytes.Length);
    stream.Write(bytes, 0, bytes.Length);
}

stream.Write(RedisMessage.Crlf, 0, 2);
}

我不明白为什么,在int64的两位数以上,long是在ascii中编码?

为什么不使用byte []?我知道,我可以使用byte []覆盖来执行此操作,但我只想了解此实现以优化我的。可能与Redis存储有关系。

提前谢谢Marc:)

P.S:我对你的下一个主要版本仍然非常热衷,因为我可以使用长值键而不是字符串。

1 个答案:

答案 0 :(得分:2)

它以ASCII编写,因为redis protocol要求的内容。

如果仔细观察,始终编码为ASCII - 但对于最常见的情况(0-9,10-99)我特别套装它,因为这些是非常简单的结果:

 x => $1\r\nX\r\n
xy => $2\r\nXY\r\n

其中xy是0-99范围内数字的前两位数,XY是这些数字(作为数字)的偏移量由48('0') - 所以十进制17成为字节序列(十六进制):

24-32-0D-0A-31-37-0D-0A

当然,这也可以简单地通过顺序写入每个数字并将数字值偏移48('0')来实现,并处理负号 - 我想答案就是“因为我编码了它是简单但明显正确的方式“。考虑值-123 - 编码为$4\r\n-123\r\n(嘿,不要看我 - 我没有设计协议)。它有点尴尬,因为它需要首先计算缓冲区长度,然后那个缓冲区长度,然后写入值 - 记住以100s,10s,1s的顺序写入(这比写入要困难得多)反过来说。)

完全愿意重温它 - 简单地说:它有效。

当然,如果你有一个可用的暂存缓冲区,它就变得微不足道了 - 你只需按照简单的顺序编写它,然后反转暂存缓冲区的部分。我会检查一下是否有空(如果没有,添加一个是不合理的。)

我还应该澄清:还有整数类型,它将-123编码为:-123\r\n - 然而,从内存中有很多地方,这些不起作用