zset中score使用注意事项

zset语法如下:

zset key score member

实际开发中使用zset做排序,在应用层score必须是个64位整型,例如下面场景:

  1. 高8位代表一个排序规则
  2. 次8位代表一个排序规则
  3. 再一个16位代表一个排序规则
  4. 低32位代表一个排序规则

按照上面的顺序生成一个64位整型,例如生成64位数为144396670029746945,实际上Redis内部采用的是双精度64位浮点数(double)来存储score的,这就带来了精度问题, 而double能够精确表达的整数区间为[-(2^53),+(2^53)],即:-9007199254740992和9007199254740992之间的所有整数。具体可以参考官方文档

例如按照上面的规则生成的整数进行存储:

zadd test 144396670029746945 1

当使用redis-client查看时,结果如下:

zrange test 0 -1 withscores
"1"
"1.4439667002974694e+017"

当使用可视化redis client工具查看时,结果如下:

144396670029746940

很显然丢失了精度

正确的用法


分两种情况:

  1. 不在乎精度

    在C++应用层应先将结果进行atof,转换为double,再将double转换为int64,如果直接将redis server返回的结果进行atoll很容易出错,例如对结果atoll(“1.4439667002974694e+017”), 取得的值为1。

  2. 对精度有严格要求

    如果对精度有严格要求,那么取值范围应该在这个区间[-9007199254740992,9007199254740992]

通常使用zset作为排行榜,那么对精度有严格要求,毕竟不希望出现两个第一名的情况