文章内容更新请以 WGrape GitHub博客 : 集合运算的过程分析与架构设计 为准
前言
本文原创,著作权归WGrape所有,未经授权,严禁转载
一、问题背景
对于实时性的集合运算,PHP+Redis架构在小数据量和低并发的场景下还是可行的,一旦数据量和并发上升,这种架构就会暴露出各种问题
- 网络流量过大,占用带宽过多
- 运算性能低下,无法快速完成
- 等等 … …
如何对现有架构升级 ?
二、过程分析
当外部请求通过网络到达时,服务内部会先获取到待计算的数据,经过在内存中的计算,最终处理结果并通过网络返回。
在整个过程中,主要分为网络、获取待计算数据、内存计算、处理结果四部分
1、网络
(1) 作用
主要承载业务方请求的接收,响应
此外可能还会有请求Redis、Redis和Cache间的同步等操作会使用到网络
(2) 业务协议
优先支持HTTP协议
2、获取待计算数据
(1) 数据源有哪些
可用的数据源主要有Redis和本地Cache
① Redis
如果需要的数据不在Cache中,则通过请求Redis的方式获取数据。但由于请求Redis大量数据时会严重占用带宽,所以必须提供Redis限流模块来解决此问题
② 本地Cache
把部分Redis数据以文件或内存Cache的方式,存储至本地,减少每次都请求Redis的网络开销。
但使用Cache会面临数据不一致的问题,那么如何做到数据同步 ?在数据同步时,又如何解决数据竞争问题 ?这些问题都交给数据同步模块解决
(2) 什么是待计算数据
数据源中有很多很多数据,但每次集合运算只需要与此次计算有关的数据,这些数据就是待计算数据
(3) 如何筛选待计算数据
由业务方请求中的参数控制决定,如业务方请求参数Key=A&Key2=B,那么此次集合运算中的待计算数据,就是数据源中Key为A和B的两个数据
① 数据源中待计算数据的类型
- 在Redis中 :支持 List / Set / Sorted Set 三种类型,元素为整型数字
- 在Cache中 :二进制存储、JSON存储、内存变量等
(5) Redis限流模块
业务请求中如果传递了需要计算的数据量(不传递则视为使用默认值),那么系统会对此数据量做评估,做出是否需要限流的决策
具体的限流方案是分批获取,如业务要求计算1000万的数据量,则分10次获取数据,每次只获取100万的数据
(6) Cache数据同步模块
先在架构中留下此模块的设计,待一期完成后补充
3、内存计算
(1) 数据载入内存
从基本过程中可知获取待计算数据后,会把数据载入内存中
① 内存中待计算数据的类型
整型Slice
(2) 如何进行集合运算
通过位运算与位向量技术,或使用golang-set实现
4、处理结果
当返回的数据量过大时,需要对返回的数据做压缩(gzip)处理
三、架构设计
1、架构概览
2、接入层
使用Nginx + Lua实现高并发、高性能、高可用的服务
3、网络层
主要负责并支持各种协议的网络通信、Gzip压缩
4、控制层
对业务方的请求做解析,包括参数解析,数据量评估,数据源的选择,限流等
5、数据层
提供Cache、Redis两种数据源
6、计算层
把数据载入内存,进行集合运算
7、响应层
对返回结果做加密、压缩等额外的处理操作