redis 现象求解 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zcj2898
V2EX    Redis

redis 现象求解

  •  
  •   zcj2898 2017-10-11 20:35:31 +08:00 6841 次点击
    这是一个创建于 2931 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 redis 存储大整数,出现精度丢失问题。网上查了下找不到有关信息。有没有大佬来解释一波?感激不尽!以及这个问题如何解决?

    127.0.0.1:6379> zadd test 14338073069842465 2239

    (integer) 0

    127.0.0.1:6379> zscore test 2239

    "14338073069842464"//储存 65,拿到 64

    127.0.0.1:6379> zadd test 14338073069842466 2239

    (integer) 0

    127.0.0.1:6379> zscore test 2239

    "14338073069842466"//储存 66,拿到 66

    127.0.0.1:6379> zadd test 14338073069842463 2239

    (integer) 0

    127.0.0.1:6379> zscore test 2239

    "14338073069842464"//储存 63,拿到 64

    127.0.0.1:6379> zadd test 14338073069842462 2239

    (integer) 0

    127.0.0.1:6379> zscore test 2239

    "14338073069842462"//储存 62,拿到 62

    18 条回复    2017-10-12 16:12:06 +08:00
    crystom
        1
    crystom  
       2017-10-11 20:44:59 +08:00
    9007199254740992
    crystom
        2
    crystom  
       2017-10-11 20:45:50 +08:00
    Redis sorted sets use a double 64-bit floating point number to represent the score. In all the architectures we support, this is represented as an IEEE 754 floating point number, that is able to represent precisely integer numbers between -(2^53) and +(2^53) included. In more practical terms, all the integers between -9007199254740992 and 9007199254740992 are perfectly representable. Larger integers, or fractions, are internally represented in exponential form, so it is possible that you get only an approximation of the decimal number, or of the very big integer, that you set as score
    zcj2898
        3
    zcj2898  
    OP
       2017-10-11 20:49:18 +08:00
    @crystom 谢谢了,用来实现游戏排行,高 32bit 是排行值,低 32bit 是时间戳,有什么解决方案吗~
    des
        4
    des  
       2017-10-11 20:52:23 +08:00 via Android
    @zcj2898 为什么要这么存?是有什么特殊需求嘛?
    zcj2898
        5
    zcj2898  
    OP
       2017-10-11 20:58:07 +08:00
    @des 游戏从业者,比如英雄排行榜数据,依次比较英雄的战力、等级、星级、阶级如果都一样就比先到这个战力的时间戳,依次把这些值序列后就很容易造成 value 很大超过楼上说的 53 位精度。
    td width="10" valign="top">
    daybyday
        6
    daybyday  
       2017-10-11 21:19:41 +08:00
    合理分配好:"战力、等级、星级、阶级、时间戳" 各项占用的位数,使得 score 值总大小在精度不丢失范围内
    你这场景,比较好的解决方案是:牺牲时间戳的精度,单位存分,甚至存小时,另外存成偏移值,而不是绝对值,也能省一些
    crystom
        7
    crystom  
       2017-10-11 21:46:23 +08:00
    在 redis2.6 上可能可以使用 lua script 解决(我没实际用过),不过我比较赞同楼上,如果让我做的话,会在业务上妥协精度。
    WinterWu
        8
    WinterWu  
       2017-10-11 22:29:48 +08:00
    1. 如楼上所言,想办法缩减长度,牺牲点时间戳精度之类 /尤其看需要的比较时间范围,用偏移值解决,比如今天零点开始的偏移值,可以算算去掉多少位数
    2. 改成字符串格式,利用字符串排序
    3. 分段-类似分桶,将分值按照范围分别保存和排序,然后在每个范围内仅保存偏移
    zcj2898
        9
    zcj2898  
    OP
       2017-10-11 23:48:08 +08:00
    感谢各位回复,我缩减一下各数据所占的位数。就是排行榜原来的数据要作废了。
    wsy2220
        10
    wsy2220  
       2017-10-11 23:52:56 +08:00
    存字符串吧
    lslqtz
        11
    lslqtz  
       2017-10-12 00:11:38 +08:00
    @zcj2898 对原来的数据进行解析转成新数据嘛
    dangyuluo
        12
    dangyuluo  
       2017-10-12 00:17:06 +08:00
    原来的数据也不用作废。写个小程序转换一下就好。
    czheo
        13
    czheo  
       2017-10-12 03:47:48 +08:00
    可以存 score + timestamp/2^31。(2^31 - 1 是 timestamp 最大值,可以用到 2038 年)
    比如积分 100,timestamp= 1507750681,存 100 + 1507750681/2^31 = 100.70210112305。
    当 score 不够大,精度准确。score 过大,小数位精度会自动丢失。

    如果为了 debug 方便,也可以存 score + timestamp/10^10。
    crystom
        14
    crystom  
       2017-10-12 08:57:11 +08:00 via iPhone
    @czheo 浮点浮点,除以几的话和不除差不多的
    wombat
        15
    wombat  
       2017-10-12 09:13:53 +08:00
    base64 一下,用的时候在解开不就好了。
    zhx1991
        16
    zhx1991  
       2017-10-12 12:56:17 +08:00
    存成 string 自己转
    yexiangyang
        17
    yexiangyang  
       2017-10-12 16:00:55 +08:00 via iPhone
    @zhx1991 zadd 不支持字符串分值
    czheo
        18
    czheo  
       2017-10-12 16:12:06 +08:00
    @crystom 想想好像确实差不多。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     6063 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 02:12 PVG 10:12 LAX 19:12 JFK 22:12
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86