ホームページ  >  記事  >  Java  >  便利な統計受注収入 (1)

便利な統計受注収入 (1)

coldplay.xixi
coldplay.xixi転載
2020-10-21 17:18:272211ブラウズ

java Basic Tutorial 列では、注文収入を簡単にカウントする方法を示します。

便利な統計受注収入 (1)

#はじめに

統計的な注文収入は次のとおりです。 -commerce これは、このタイプの APP によくある問題です。通常の要件には、通常、ユーザーのメリット

日次/月次/年次レポート が含まれます。これらのレポート タイプのデータは、テーブル設計やプログラム設計に大きな課題をもたらします。従来型集計クエリ 損益計算書のデータが大きくなるにつれて、計算書のクエリ時間は徐々に長くなります。このとき、より効率的にクエリを実行できるように損益計算書を設計する方法を考える必要があります。デザインによって統計的収入をシンプルにすることができますか?

#要件

    収入の種類は次のように分類されます。・発注収入、シェアオーダー収入、分配収入、活動収入
  • 当日の収入の統計、当月の収入を計算します。上映時間に基づく 期間中の収入。

#思考

注文テーブルは必ず必要です。注文テーブルを作成・修正する際は、収入テーブルも同時に作成・修正してください。注文テーブルには自己購入と共有注文のみが記録され、配布やイベントギフトの収入は記録されません。注文テーブルにのみ記録されます。特別なビジネスで損益計算書を作成します。次に、その日をディメンションとして使用して、ユーザー

日次収入レポート

を作成します。単一行のレコードがユーザーの収入に書き込まれます。 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 つの技術フレームワークを簡単に紹介しましょう:

  • canal: 主な目的は、MySQL データベースの増分ログ分析に基づいて、増分データのサブスクリプションと消費を提供することです。
  • RocketMQ: オープンソースの分散メッセージ システムは、高可用性の分散クラスター テクノロジーに基づいており、低遅延で信頼性の高いメッセージ パブリッシュおよびサブスクリプション サービスを提供します。

注: 私は aliyun の Family Bucket を使用しています。MQ と mysql はどちらも Alibaba Cloud のものです。自己構築サーバーの場合は、違いがある可能性があります。試してみます。

提案プロセス

  1. ## 損益計算書の作成または変更中に、canal を介して mysql 損益計算書の binlog ログを監視します。
  2. canal は変更を検出し、変更された JSON メッセージを組み立てて送信します。 RocketMQ TOPIC の事前定義されたもの。
  3. プログラムは、この TOPIC と異種収入日次レポートを使用します。

canal 設定パート##canal のインストールについては公式ドキュメントを参照してください。 解凍後、3 つのディレクトリを含む canal フォルダーが得られます。
  • #bin: 起動スクリプトと再起動スクリプトを保存します
  • #conf: コア構成ファイルを保存します
  • lib: コア jar パッケージの保存
  • conf フォルダー内の conf/canal.properties コア構成ファイルと conf/example/instance.properties 単一監視ノードに注目する必要があります。設定ファイル

注: 監視テーブルの記述ルール形式については、監視テーブルの記述ルールを参照してください

#Startup
cd /canal/bin
./start.sh
canal日志中出现
 the canal server is running now ......
example日志中出现
 init table filter : ^tablename
 xxxxxxxxx , the next step is binlog dump

は成功したことを意味します。大きな前進です。運河監視は正常に実行されています。

RocketMQ部分

如果用的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 サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。