@yanglfyangl
2018-06-01T03:58:59.000000Z
字数 2192
阅读 559
统计分析引擎的由来主要是为了支持各种复杂的统计及分析需求。
主要的统计维度有:
- 按时间统计(固定日期。。。最近几天。。。)
- 按状态统计(各种状态)
- 按类型统计(各种类型)
- 按位置统计(城市/区。。。)
- 按阶段(时间阶段,人数阶段,活跃值阶段。。。)
- ......
主要的排序维度有:
- 按时间
- 按人数
- 按位置或距离
- 按等级
- ......
还需要支持变化统计:
- 等级 变化列表
- 趣豆 变化列表
- 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存一份,一旦出现配置项改变的情况,则基于基础数据重新生成一份。
- 对于复杂查询,简化成简单查询后,通过交并集操作来进行。