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
总结
整体上看, 最大弊端:极大增大了前后端的复杂度,前后端都需要进行位操作,及前后端需要形成对于每个位的实际意义的一种共识;
最大优点:节省存储空间,用户设置成为用户表的一个小小整型字段,省去了额外维护一张与用户表保持一一对应关系的用户设置表;