• 线上问题之Java数字范围引发的异常


    1 场景复现

    线上服务做A/B测试,根据a数据切分流量,
    这里直接采用hashCode,取最后两位0-99作为流量通道,
    取0-10通道测试功能,在做流量切分时,发现流量并比例并不是1:9,
    而是达到了惊人的1:1,于是开始排查a数据的分布是否均匀,发现,是均匀的,然后,对a数据进行独立数统计,
    抽取数量较多的a数据进行hashCode测试,发现计算之后出现负数,这些负数都挤在了[0,9]这个通道,
    因为流量切分直接使用traffic<=10,所以出现流量比例异常的问题。

    2 方案

    重新设计逻辑:取结果的绝对值:Math.abs(result)。

    3 原理

    3.1 数据轮转

    数据在取值范围内轮转,当数据值超过取值范围时,
    按照约定计算新值,本文以byte为例,探究数据是如何轮转的。
    1byte占用的存储空间为8bit,即1byte=8bits,取值范围:[ − 2 7 -2^7 27, 2 7 2^7 27-1],
    总共可以存储256个数据,数据轮转示意图如下图所示,
    数据轮转计算规则:
    (1)绝对值按位取反
    (2)加1;
    (3)变更符号。

    在这里插入图片描述

    3.2 Code

    byte测试数据轮转样例如下,
    数据转换过程在注释中给出。

    package com.monkey.java_study.functiontest;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.junit.Test;
    
    import java.io.ByteArrayOutputStream;
    
    /**
     * Byte测试.
     *
     * @author xindaqi
     * @date 2021-12-01 17:48
     */
    public class ByteTest {
    
        private static final Logger logger = LogManager.getLogger(ByteTest.class);
    
        @Test
        public void byteRange() {
            Byte byteMax = Byte.MAX_VALUE;
            Byte byteMin = Byte.MIN_VALUE;
            logger.info(">>>>>>>>Byte max value:{}, byte min value:{}", byteMax, byteMin);
            // 在取值范围内,不进行操作
            Byte var127 = (byte) 0b0111_1111;
            // 128(1000,0000)->绝对值按位取反(0111,1111)->加1(0111,1111+1)=128->变更符号(-128)
            Byte var128 = (byte) 0b1000_0000;
            logger.info(">>>>>>>>Var127:{}, Var128:{}", var127, var128);
            // 129(1000_0001)->绝对值按位取反(0111,1110)->加1(0111,1110+1)=127->变更符号(-127)
            Byte var129 = (byte) 0b1000_0001;
            // -129(-1000,0001):绝对值按位取反(0111,1110)->加1(0111,1111+1)=127->变更符号(127)
            Byte varNegative129 = (byte) -0b1000_0001;
            logger.info(">>>>>>>>Var129:{}, VarNegative129:{}", var129, varNegative129);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    测试结果如下图所示,与计算逻辑一致。
    在这里插入图片描述

    4 小结

    • 数据取值在对应的范围内,直接使用,超出范围,重新进行计算,并使用在数据范围内轮转;
    • 数据轮转规则:
      • 绝对值按位取反;
      • 加1;
      • 变更符号。
  • 相关阅读:
    windows关闭nginx
    Win软件 - (Net-Framework)已处理证书链,但是在不受信任提供程序信任的根证书中终止
    移动端项目创建,脚手架,vant3移动开发的UI组件
    SuperMap iClient3D for WebGL教程(S3MTilesLayer)- 显示优化设置
    前端中有序标签的使用
    【分布式幂等性】高并发下如何保证接口的幂等性?
    React的diff算法原理
    ARM64汇编06 - 基本整型运算指令
    数据艺术:精通数据可视化的关键步骤
    iOS消息转发流程
  • 原文地址:https://blog.csdn.net/Xin_101/article/details/127409688