多个开关标志位存储的设计思路

1,972 阅读2分钟

前端时间配合前端需求的时候出现一个场景,需要存储大量的state状态,例如是否开启推送、短信、夜间模式等状态。如果使用单表多字段去存这些信息就显得得不偿失。考虑到开关只有开关状态的情况下,使用01二进制的方式来存可能非常不错。

mysql数据库中:INT类型(0,4 294 967 295)可存储10位数字,也就是可以表示10个标志位开关。一般是够用的,如果不够那么可以考虑BIGINT(0,18 446 744 073 709 551 615)扩展到20位,比如:010101010101001010100......。

如果说20位还是不满足我们业务需求,那么其实存储的时候进行2进制转10进制,10位的1111111111转换成10进制只有1023一个SMALLINT类型即可存储。最大优化了mysql的存储内容,那么为什么我们要考虑直接用二进制的方式存呢,其实就是为了方便易读,如果是个标志位情况那么11110,最低位表示推送开关,那么只要我们字段注释写的ok,代表的含义基本上是非常清楚的,推送处于关闭状态。

数据库存储解决了,那么在程序里面应该如何更方便的存储呢?刚开始考虑到考虑到可以用二进制运算来方便运算。

如果当前场景有三个标志位,‘101’来表示 ‘open close open’ 三个开关。

场景1:我想知道某个开关是否开启

  private static boolean getBit(int num, int i)
   {
      //true 表示第i位为1,否则为0
      return ((num & (1 << i)) != 0);
   }

场景2:开启功能

    //将 整数 num 的第 i 位的值 置为 1
    private static int getBit(int num, int i)
    {
        return (num | (1 << i));
    }

场景3:关闭功能

    //将 整数 num 的第 i 位的值 置为 1
    private static int getBit(int num, int i)
    {
       int mask = ~(1 << i);
       return (num & (mask));
    }

实际应用配合缓存,这样操作的效率感觉还是可以的。

如有不妥之处,请指明谢谢。