HiSEN

二进制的应用

一、背景

之前京东组里有同事使用二进制优化支付密码打标性能(大促 QPS 数百万),节省内存资源。
随说:存二进制报文小,传输快,反序列化快(之前存 JSON 对象),节省缓存。

目前公司遇到个套餐打标,也通过二进制实现简单高效得解决掉了。
随说:目前倒不是要求性能,只是这么设计扩展性好,操作简单。

知识点:二进制、与运算

二、设计

打标,无非就是识别某个东西是不是包含某些属性。
那么有什么好的办法能做到通用与高效?
如果固定映射,扩展性不好,查询逻辑费劲,存储成本偏高。

目前相对较好的方案是通过二进制位来做标记,再结合与运算,快速找出数据。
随说:Java MySQL 均支持与运算

套餐VIP1VIP2VIP3标记值
A1117
B1106
C1004

如上表所示,相应套餐的购买资格标记。

A 套餐所有会有均可购买
B 套餐 VIP3 不能购买
C 套餐仅 VIP1 可购买

对相关标记进行入库处理:A=7,B=6,C=4;

正常思维,需要存三个字段,没有扩展性,性能还差。
使用二进制,结合与运算,降本(计算、传输、匹配)增效(性能提升)。

三、代码

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
Integer a = 7;
Integer b = 6;
Integer c = 4;
List<Integer> suit = Lists.newArrayList(a, b, c);
System.out.printf("支持 VIP1 (0100=4)的套餐:" + Arrays.toString(suit.stream().filter(e -> (4 & e) != 0).toArray()));
System.out.printf("支持 VIP2 (0010=2)的套餐:" + Arrays.toString(suit.stream().filter(e -> (2 & e) != 0).toArray()));
System.out.printf("支持 VIP3 (0001=1)的套餐:" + Arrays.toString(suit.stream().filter(e -> (1 & e) != 0).toArray()));

// 支持 VIP1 (0100=4)的套餐:[7, 6, 4]
// 支持 VIP2 (0010=2)的套餐:[7, 6]
// 支持 VIP3 (0001=1)的套餐:[7]
}

四、总结

系统流量小的时候
粗糙烂制也不是不能用
但是当系统流量大了就得想办法优化:CPU、传输、存储
很多时候往往利用简单的原理解决大的问题,只是很多时候限于认知不知道可以这么用。

说到底还是要知其然,更要知其所以然。