java Basic Tutorial 列では、注文収入を簡単にカウントする方法を示します。
日次/月次/年次レポート が含まれます。これらのレポート タイプのデータは、テーブル設計やプログラム設計に大きな課題をもたらします。従来型
集計クエリ 損益計算書のデータが大きくなるにつれて、計算書のクエリ時間は徐々に長くなります。このとき、より効率的にクエリを実行できるように損益計算書を設計する方法を考える必要があります。デザインによって統計的収入をシンプルにすることができますか?
を作成します。単一行のレコードがユーザーの収入に書き込まれます。 Reduce
ユーザーの日/月/年収を計算する際のデータ量をクエリします。単一のユーザーを例に取ると、ユーザーを分割しても最大 31
個のデータしか生成されません。月のデータ これは制御可能な成長率です 損益計算書を使用する場合、損益計算書のデータはユーザーの発注数と 1 対 1 に対応するため、発注金額が 1 対 1 に対応します。ユーザーの数が多い場合、テーブルは非常に大きくなります。ユーザー数が増加し始める初期段階では、この方法を使用して、大量のデータ量の統計を回避できます。その後、ユーザー数が増加すると、日次レポート データが増加する場合は、テーブルの分割を検討できます。<h3 style="margin-top: 30px; margin-bottom: 15px; padding: 0px; font-weight: bold; color: black; font-size: 20px; margin: 20px auto 5px; border-top: 1px solid rgb(221, 221, 221); box-sizing: border-box;" data-id="heading-6">
<span class="prefix" style="display: none;"></span><span class="content" style="margin-top: -1px; padding-top: 6px; padding-right: 5px; padding-left: 5px; font-size: 17px; border-top: 2px solid rgb(33, 33, 34); display: inline-block; line-height: 1.1;">目に見える問題</span><span class="suffix" style="display: none;"></span>
</h3>
<ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;">
<li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">元の注文が反映されていないため、日次収益レポートを同期するタイミングに問題があります。操作が非常に複雑です。収入の書き込みと日次収入データの計算と書き込みを同時に行うのは複雑で、コードの結合度が高すぎます。損益計算書の異質性を利用して日次収入レポートを生成する方法はありますか? </section></li>
<li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500; font-size: 15px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">収入は日次レポートに書き込まれますが、レンダリングの要件を満たすために、SQL ステートメントを複数回クエリする必要がある場合があります。使用する集計 SQL ステートメントをできるだけ少なくする方法はありますか?プログラムの効率に影響を与えずに?</section></li>
</ul>
<h2 style="margin-top: 30px; margin-bottom: 15px; padding: 0px; font-weight: bold; color: black; font-size: 22px; margin: 10px auto; height: 40px; background-color: rgb(251, 251, 251); border-bottom: 1px solid rgb(246, 246, 246); overflow: hidden; box-sizing: border-box;" data-id="heading-7">
<span class="prefix" style="display: none;"></span><span class="content" style="margin-left: -10px; display: inline-block; width: auto; height: 40px; background-color: rgb(33, 33, 34); border-bottom-right-radius: 100px; color: rgb(255, 255, 255); padding-right: 30px; padding-left: 30px; line-height: 40px; font-size: 16px;">実現</span><span class="suffix"></span>
</h2>
<p style="padding-top: 8px; padding-bottom: 8px; margin: 0; color: black; box-sizing: border-box; margin-bottom: 16px; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 15px; text-align: start; white-space: normal; text-size-adjust: auto; line-height: 1.75em;"> 上記の問題をまとめました。データ収集を開始しました。最後に、異種混合ソリューションとして <code style="font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(239, 112, 96);">canal
RocketMQ
を使用しました。
この 2 つの技術フレームワークを簡単に紹介しましょう:
注: 私は aliyun の Family Bucket を使用しています。MQ と mysql はどちらも Alibaba Cloud のものです。自己構築サーバーの場合は、違いがある可能性があります。試してみます。
cd /canal/bin ./start.sh
canal日志中出现 the canal server is running now ...... example日志中出现 init table filter : ^tablename xxxxxxxxx , the next step is binlog dump
如果用的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基础教程
以上が便利な統計受注収入 (1)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。