@yanglfyangl
2018-06-01T03:58:59.000000Z
字数 2192
阅读 608
统计分析引擎的由来主要是为了支持各种复杂的统计及分析需求。
主要的统计维度有:
- 按时间统计(固定日期。。。最近几天。。。)
- 按状态统计(各种状态)
- 按类型统计(各种类型)
- 按位置统计(城市/区。。。)
- 按阶段(时间阶段,人数阶段,活跃值阶段。。。)
- ......
主要的排序维度有:
- 按时间
- 按人数
- 按位置或距离
- 按等级
- ......
还需要支持变化统计:
- 等级 变化列表
- 趣豆 变化列表
- XXX 变化列表
class TimeSatisQueryVo:{public String KEY;public Date startTime;public Date endTime;}class TagSatisQueryVo:{public String KEY;public Date startTime;public Date endTime;}。。。。。。class AnalysisEngine:{//初始化部分public void getInstance(){};public void loadRules(){}; // 注:如果Rules发生变化,可能会导致数据重新处理,慎重。//数据更新部分public void addOrUpdateData(T){};public void deleteData(String ID){};//数据统计部分public List<T> queryStatistics(){}; //public List<T> queryOrder(){}; //public List<T> queryChanges(){}; //public List<T> complexQuery(){}; //复杂查询。(能支持的就是基于上面的查询的交并集)}
初始化配置文件
{"statistics":[{key:""type:"TIME" //如果是时间,则每天的结果计算后放到一起。field:"" //指DTO或Map中对应的字段名。},{type:"TAG"field:""}],"Order":[{type:"TIME" //如果是时间,每天的数据放到一起。field:""},{type:"POSITION"field:""},"Changes":[{type:"TIME" //如果是时间,每天的数据放到一起。Interval:"Week" // 每周的field:""},}
数据传入引擎
//对于每个输入Bean,需要对应一个分析引擎。Class CrowdAnalysisEngine:{void example(){AnalysisEngine.Load(BeanCrowdAnalysisJson);AnalysisEngine.addOrUpdateData(userBean);AnalysisEngine.deleteData(userBean.getID());}}
addOrUpdateData的逻辑
public addOrUpdateData(){for (statistics list) {if(type == "TIME"){//主要逻辑是按规则将数据按天进行统计。//这样获取过去多少天,或更复杂的统计的时候,就可以进行简单的加减法就可以了。//key值的定义String key = "statistics" + "Today Date"+ [item].field;value = KVDB.getKey(key);KVDB.setValue(key, value + [item].field.data);}if(type == "TAG"){//主要逻辑是按规则将数据按标签进行计算并存储。//key值的定义String key = "Order" + [item].field;value = KVDB.getKey(key);KVDB.setValue(key, value + [item].field.data);}}for (Order list) {和上面的逻辑基本是一样的。}for (Change list) {if(type == "TIME" && intervel == "week") {//主要逻辑是将数据每周都存一份到zset中,获取数据时取交集。//如果数据量过大的话,则批量交给Spark处理,处理的结果存在KV库中。//key值的定义String key = "Order" + [item].field;value = KVDB.getKey(key);KVDB.setValue(key, value + [item].field.data);}}}
query的逻辑
public List<String> queryStatistics(TimeSatisQueryVo vo){//根据Vo找出对应的Key来;//根据Vo找出对应的时间来。//如果需要取出多个后相加,则相加。//计算结果返回给前端。}public List<String> complexQuery(List<QueryVo> voList){// 复杂查询就是根据各种vo来进行查询(并行查询)// 查询的结果还是放到存到缓存中的// 进行并集操作}
最核心的实现逻辑是:
- 对每个配置的项,存到不同K-V set或zSet中,取的时候,直接取(用空间换时间)
- 将基本数据按ID存一份,一旦出现配置项改变的情况,则基于基础数据重新生成一份。
- 对于复杂查询,简化成简单查询后,通过交并集操作来进行。