java基礎教學專欄帶大家了解如何便捷的統計訂單效益。
#統計訂單收益是做電商類型的APP老生常談的問題.常規需求大致有用戶收益日報/月報/年報
.這些報表型的數據對錶設計和程序設計有著不小的挑戰.常規的聚合查詢
語句的查詢時間會隨著收益表資料日漸龐大而逐漸變長。這時候就需要思考如何設計收益表可以更有效率的查詢?怎樣的設計才可以讓統計收益變得簡單?
#訂單表是肯定需要的.在寫入或修改訂單表的時候同步寫入修改收益表.只有自購和分享訂單會記錄到訂單表中,分銷以及活動贈送收益只在特殊業務中寫入收益表.再以日為維度,建立一張用戶
收益日報表.單行記錄寫入用戶當天收益狀況.
降低
總結出上面這些問題.我開始了資料收集.最終採用canal
RocketMQ
做為異質方案.
簡單介紹一下這兩款技術框架:
註:我用的aliyun的全家桶,MQ和mysql都是阿里雲的,如果是自建伺服器的可能有區別,我在後面盡量標出
canal的安裝請參考官方文檔 解壓縮後可得到一個canal資料夾,包含三個目錄
#conf:存放核心設定檔
我們需要專注於conf資料夾裡的conf/canal.properties核心設定檔以及conf/example/instance.properties單一監控節點設定檔
# tcp, kafka, RocketMQ,这里默认是tcp读取模式,采用RocketMQ需要将其改变为RocketMQ模式 canal.serverMode = RocketMQ # 如果是aliyun的RocketMQ需要配置以下两个KEY,ak/sk canal.aliyun.accessKey =xxxxxxx canal.aliyun.secretKey =xxxxxxx # 监控的节点名称.这个默认就是example如果有多节点可以逗号隔开,如下方的例子 canal.destinations = example,sign # 如果是aliyun的RocketMQ需要修改canal.mq.accessChannel为cloud默认为local canal.mq.accessChannel = cloud #MQ的地址,需要注意这里是不带http://,但是需要带端口号 canal.mq.servers = #rocketmq实例id canal.mq.namespace =
#mysql地址 canal.instance.master.address= #以下两个参数需要在开启数据库binlog日志后得到,在数据库查询界面输入查询语句`show master status`,canal.instance.master.journal.name对应File参数,canal.instance.master.position对应Position参数 canal.instance.master.journal.name= canal.instance.master.position= #数据库的账号密码 canal.instance.dbUsername= canal.instance.dbPassword= #需要监控变动的表 canal.instance.filter.regex=xxx.t_user_order,xxx.t_user_cash_out #定义发送的mq生产组 canal.mq.producerGroup = #定义发送到mq的指定主题 canal.mq.topic=
canal日志中出现 the canal server is running now ...... example日志中出现 init table filter : ^tablename xxxxxxxxx , the next step is binlog dump
表示你已經成功了一大步,canal監控已正常運作.
如果用的aliyun的RocketMQ,配置代码部分直接可参考文档 自建的RocketMQ也可参照简单的消费例子监控对应的TOPIC即可 消费Canal发来的数据,格式如下:
{ "data":[ { //单个修改后表数据,如果同一时间有多个表变动会有多个该JSON对象 } ], "database":"监控的表所在数据库", "es":表变动时间, "id":canal生成的id, "isDdl":Boolean类型,表示是否DDL语句, "mysqlType":{ 表结构 }, "old":如果是修改类型会填充修改前的值, "pkNames":[ 该表的主键,如"id" ], "sql":"执行的SQL", "sqlType":{ 字段对应的sqlType,一般使用mysqlType即可 }, "table":"监控的表名", "ts":canal记录发送时间, "type":"表的修改类型,入INSERT,UPDATE,DELETE" }
MQ消费代码主要用了反射,映射到对应的表
//这里的body就是Canal发来的数据 public Action process(String body) { boolean result = Boolean.FALSE; JSONObject data = JSONObject.parseObject(body); log.info("数据库操作日志记录:data:{}",data.toString()); Class c = null; try { //这里监控了订单和收益表分别做订单统计和收益日报统计 c = Class.forName(getClassName(data.getString("table"))); } catch (ClassNotFoundException e) { log.error("error {}",e); } if (null != c) { JSONArray dataArray = data.getJSONArray("data"); if (dataArray != null) { //把获取到的data部分转换为反射后的实体集合 List list = dataArray.toJavaList(c); if (CollUtil.isNotEmpty(list)) { //对修改和写入操作分别进行逻辑操作 String type = data.getString("type"); if ("UPDATE".equals(type)) { result = uppHistory(list); } else if ("INSERT".equals(type)) { result = saveHistory(list); } } } } return result ? Action.CommitMessage : Action.ReconsumeLater; } /** * @description: 获取反射ClassName * @author: chenyunxuan */ private String getClassName(String tableName) { StringBuilder sb = new StringBuilder(); //判断是哪张表的数据 if (tableName.equals("t_user_income_detail")) { sb.append("cn.mc.core.model.order"); } else if (tableName.equals("t_user_cash_out")) { sb.append("cn.mc.sync.model"); } String className = StrUtil.toCamelCase(tableName).substring(1); return sb.append(".").append(className).toString(); } /** * @description: 写入对应类型的统计表 * @author: chenyunxuan */ private <T> Boolean saveHistory(List<T> orderList) { boolean result = Boolean.FALSE; Object dataType = orderList.get(0); //用instanceof判断类型进入不同的逻辑处理代码 if (dataType instanceof TUserIncomeDetail) { result = userOrderHistoryService.saveIncomeDaily(orderList); } else if (dataType instanceof UserCashOut) { result = userCashOutHistoryService.delSaveHistoryList(orderList); } return result; }
saveIncomeDaily伪代码
public synchronized Boolean saveIncomeDaily(List orderList) { //循环收益明细记录 ....... //通过创建时间和用户id查询收益日报表中是否有当日数据 if(不存在当日数据){ //创建当日的收益日报表记录 ..... } //因为不存在当日记录也会立即写入当日的空数据,所以下面的流程都是走更新流程 //更新当日数据 ....... return Boolean.TRUE; }
注:代码中应该多打一些日志,方便产生异常收益数据后的校对
至此一个基于canal
+RocketMQ
的收益日报统计异构方案就完成了,下一篇会围绕本文提到的第二个问题减少聚合SQL的产生展开.敬请关注.
相关免费学习推荐:java基础教程
以上是便捷的統計訂單收益(一)的詳細內容。更多資訊請關注PHP中文網其他相關文章!