目录
java位运算在实际业务中的应用 引论篇(一)java位运算在实际业务中的应用 实操篇(二)java位运算在实际业务中的应用 番外篇(三)java位运算在实际业务中的应用 总结篇 (四)
前言
任何一项方案,有利必有弊;
性能、实现复杂度、维护成本等等指标之中必定有所取舍的…
利:
- 节约了数据库的存储空间
- 网络传输更少字节
- 无需维护多表关系,原本由于字段太多需要单独建表,这张表需要和用户表关联,现在只要在用户表中加一个很短的整型字段
弊:
- 需要熟悉位操作
弊 , 乍一看只是需要开发者掌握基本位操作就行
实则带来了更大的问题
并发问题
由于页面允许很快速得来回点击,为了好的用户体验,不能限制用户点击速度
我们仔细理一下思路
单个点击某个按钮
- 前端调接口,告诉后端是哪个设置变动了,并且改变成true或者false了
- 后端需要先去数据库取当前的值,然后进行位操作,这样就进行了两次数据库操作,先select再update
- 而如果是一个设置对应一个字段(传统方法),那么是不需要查这个步骤,直接更新
- 那么有没有一种方法可以避免再查一遍吗??
- 如果修改的时候另外带上修改前的原值呢??能否可以既避免update前再select呢??
- 表面上好像可以,但仔细考虑一下这里用户的操作情景,假如用户很快得点击多个设置滑块,改变了多个值,每次改变都带上修改前的原值,问题出现了,很有可能它们带上的是同样的原值,然后修改不同的位,很显然最后的结果不是我们想要的,有并发问题
- 那么岂不是采用这种“二进制浓缩法”解决不了并发问题???!!!
- 解决这个问题也是有办法的,那就是前端直接把整个值传到后端进行直接update,而不是每次只给局部某个字段的修改,这显然增加了前端的麻烦,修改设置部分的整个位操作需要转移到前端完成,这算是这种浓缩法带来的最大弊端吧
- 那么如何维护一套统一的规则呢??实际上指的是二进制的每个位对应的意义在前后端需要保证一致
- 也有解决之道,那就是前端查询返回所有接口的时候,我不仅返回每个字段名以及对应的布尔值,还要带上每个字段名在二进制中的位置信息(可以定义一个类似数组的index的概念,从右往左)
查询的返回数据结构如下:
{
userid: 123,
setting:{
{
index: 0,
settingModule: "s_at",
enable: true,
label: "汉字解释"
},
{
index: 1,
settingModule: "s_comment",
enable: false,
label: "汉字解释"
},
{
index: 2,
settingModule: "s_msg",
enable: true,
label: "汉字解释"
},
........
}
}
前端有了索引,就可以把每个索引上填上0或者1,组成一个二进制数,然后转十进制数作为一个待修改的值,调用后端接口直接进行设置的修改,后端只需直接进行update
总结
整体上看,
最大弊端:极大增大了前后端的复杂度,前后端都需要进行位操作,及前后端需要形成对于每个位的实际意义的一种共识;
最大优点:节省存储空间,用户设置成为用户表的一个小小整型字段,省去了额外维护一张与用户表保持一一对应关系的用户设置表;