基于流式计算的多层级组织的实时报表设计
背景:
某公司,有多个组织层级,所有的员工关系都隶属于最低组织层级。
现需要实现实时报表,对每个层级的组织都可以查看其员工情况统计报表,中间层级组织的报表相当于其直属下属组织的报表汇总。报表数据可反查。
原则:
流式计算,以空间换时间、以时间换时间
方案:
信息系统在对员工信息修改时,将原始修改信息进行预处理,然后应用到该员工所属组织报表上,同步更新其所有上级组织的报表。
预处理阶段:数据预处理引擎,即将原始修改信息进行提取,加工为报表所需的数据。加工后的数据放到消息队列中待处理。详略。
实时报表阶段:实时处理引擎,提取加工员工数据,与报表定义比对,生成匹配区域,进一步生成匹配报表格:
1、如该员工为新员工,则直接将对应匹配报表格+1,匹配报表格对应员工集合增加该员工,维护该员工对应报表格集合;
2、如该员工为老员工,则取出员工对应报表格集合,与新匹配集合比较:
对原有现无的格子:原匹配格数字-1,匹配格对应员工集合删除该员工,该员工对应报表格删除该格子;
对原无现有的格子:现匹配格数字+1,匹配格对应员工集合增加该员工,该员工对应报表格增加该格子。
对原有现有的格子,如格子类型为统计格,则跳过;如格子类型为字段汇总格(如汇总收入),则根据原值和新值对匹配格数字进行调整。
查询报表阶段:取出报表模板,将报表数字填写到模板上。反查时,根据格子对应员工集合显示员工列表即可。
技术:
消息队列:RabbitMQ,其可靠性高
报表数字存放:Redis的Hashtable类型,其有快速的hashincrease操作。Hashtable的外部键名包含报表名和组织层级码参数,内部键名包含报表格名参数,值为报表格数字。
报表数字查询:取出hashtable全部数字或单个数字都非常简单,单个数字复杂度为O(1)。
报表格对应员工集合:Redis的SortedSet类型,能确保唯一性,新增和删除操作均为O(1),与Set类型相比还能支持分页查询。SortedSet的键名包含报表名和报表格名参数,值为员工所在组织代码和员工主键(组合方便查询)。即使扩展为报表内部分统计员工,部分统计组织,因报表格都是从单一实体类型统计,所以也无需保存实体类型。
查询:使用Zrangebylex进行查询。字典序设定为组织代码即可
员工对应报表格集合:Redis的Set类型。不需要分页查询,故没有使用SortedSet类型。Set的键名包含实体类型和实体主键,键值包含报表名和报表格名
无需查询
详细设计:
报表定义:
| 属性 | 含义 |
| RPTName | 定义所属的报表 |
| RangeType |
区域类型 R:单行 C:单列 MR:多行分布 MC:多列分布 |
| RangeValue |
区域范围 类型为R或C时,该值为一个整数,表示第几行、第几列 类型为MR或MC时,该值为一个数组,表示连续行或列,例如MR的[2,3]表示第2行开始的连续3行。 |
| Forumula |
取数公式 值为一个数组,格式为[属性名,操作符或函数,参数集合...] |
取数定义中的公式Forumula
| 操作符或函数 | 类型 | 适用数据类型 | 描述 | 示例 |
| =,>,<,>=,<= | 单行列 | 任意 | 比较运算 |
["年龄",">","60"] 匹配年龄大于60岁 运算根据属性类型自动确定比较方法,如数字、日期、文本等,下同。 |
| range | 单行列 | 任意 | 区间运算 |
["年龄","range","(30","[60"] 匹配年龄在30(不含)-60(含)岁区间 注:“(”表示不含,“[”表示含,没有符号的默认为含,下同。 |
| startswith | 单行列 | 文本 | 文本运算 |
["工作岗位","startswith","1"] 匹配工作岗位代码以1开始 注:属性类型不为文本时将先转换成文本再运算,下同。 |
| mrange | 多行列 | 任意 | 多区间运算 |
["年龄","mrange","","[30","[60",""] 匹配<=30,31-60,>60三个区间,并将结果赋予所匹配的具体区间。 例如当匹配第2个区间时,该定义的范围为5-7行,则该公式匹配第6行。 |
| mstartswith | 多行列 | 文本 | 文本运算 |
["工作岗位","mstartswith","1","2,"3"] 匹配工作岗位代码以1、2、3开始的,匹配多个条件的,以第一个条件为准。 |

浙公网安备 33010602011771号