Heim >Java >JavaBase >Praktische Statistiken zum Auftragseingang (1)

Praktische Statistiken zum Auftragseingang (1)

coldplay.xixi
coldplay.xixinach vorne
2020-10-21 17:18:272289Durchsuche

Die Spalte

Einfaches Java-Tutorial zeigt Ihnen, wie Sie Auftragseinnahmen bequem zählen können.

Praktische Statistiken zum Auftragseingang (1)

Einführung

Statistische Bestelleinnahmen sind ein häufiges Problem für E-Commerce-Apps. Die allgemeinen Anforderungen sind ungefähre Benutzereinnahmen Wird immer größer. Zu diesem Zeitpunkt müssen wir darüber nachdenken, wie wir die Gewinn- und Verlustrechnung effizienter gestalten können

Anforderungen

Rendering

Spezifische Bedürfnisse

    .
  • Einkommensarten sind unterteilt in: Einnahmen aus Selbstbestellungen, Einnahmen aus geteilten Bestellungen, Verteilung Einkommen, Aktivitätseinkommen
  • Statistik das Einkommen des Tages, das Einkommen des Monats
  • Das Einkommen des Zeitraums wird basierend auf der gefilterten Zeit berechnet.

Denken

Die Bestelltabelle wird unbedingt benötigt. Beim Schreiben oder Ändern der Bestelltabelle wird nur die geänderte Einkommenstabelle geschrieben Bestellungen werden in der Auftragstabelle erfasst und nur in der Gewinn- und Verlustrechnung erfasst. Verwenden Sie dann den Tag als Dimension, um eine kontrollierbare Wachstumsrate zu erstellen Verwenden Sie weiterhin die Gewinn- und Verlustrechnung, da die Datenmenge eins zu eins mit der Anzahl der vom Benutzer aufgegebenen Bestellungen übereinstimmt. Wenn die Anzahl der vom Benutzer aufgegebenen Bestellungen groß ist, wird die Tabelle sehr groß. In der frühen Phase, wenn die Anzahl der Benutzer zunimmt, kann diese Methode verwendet werden, um Statistiken mit großem Datenvolumen zu vermeiden. In der späteren Phase, wenn die Anzahl der Benutzer zunimmt, können Sie Sub-Daten in Betracht ziehen -Tische.

Sichtbare Probleme

  • Der Zeitpunkt der Synchronisierung des täglichen Einkommensberichts, da der ursprüngliche Bestellvorgang sehr kompliziert ist und das synchrone Schreiben des Einkommens und die Berechnung der täglichen Einkommensdaten erfordert und die Codekopplung zu hoch ist . Gibt es eine Methode zur Erstellung eines täglichen Einkommensberichts durch die Heterogenität der Gewinn- und Verlustrechnung?
  • Obwohl das Einkommen in den täglichen Bericht geschrieben wird, müssen möglicherweise mehrere SQL-Anweisungen erstellt werden, um den von den Renderings geforderten Effekt zu erzielen abgefragt. Gibt es eine Möglichkeit, eine Beeinträchtigung der Leistung zu vermeiden?

Implementierung

Schließlich habe ich

als heterogene Lösung übernommen canal+RocketMQ

Technologie-Stack

Eine kurze Einführung in diese beiden Technologie-Frameworks:

  • Kanal: Der Hauptzweck besteht darin, inkrementelle Datenabonnements und -nutzung basierend auf der inkrementellen Protokollanalyse der MySQL-Datenbank bereitzustellen.
  • RocketMQ: Ein verteiltes Open-Source-Messaging-System, das auf hochverfügbarer verteilter Cluster-Technologie basiert und eine hohe Latenzzeit bietet zuverlässiger Nachrichtenveröffentlichungs- und Abonnementdienst.

注:我用的aliyun的全家桶,MQ和mysql都是阿里云的,如果是自建服务器的可能有区别,我在后面尽量标出

Projektprozess

  1. Überwachen Sie das Binlog-Protokoll der MySQL-Gewinn- und Verlustrechnung über den Kanal, während Sie die Gewinn- und Verlustrechnung schreiben oder ändern.
  2. Kanal erkennt Änderungen, Zusammenbau Die geänderte JSON-Nachricht und das in RocketMQ vordefinierte TOPIC verbrauchen den täglichen Bericht „THEMA“ und „Heterogenes Einkommen“.
  3. Bitte installieren Sie den Kanal Nach der Dekomprimierung erhalten Sie einen Kanalordner mit drei Verzeichnissen
  • bin: speichert die Start- und Neustartskripte
  • conf:存放核心配置文件
  • lib: speichert das Kern-JAR-Paket

Wir müssen uns auf die Kernkonfigurationsdatei conf/canal.properties und conf/example/ konzentrieren. in der conf-Ordnerinstance.properties-Einzelüberwachungsknoten-Konfigurationsdatei Regel Format der Überwachungstabelle, siehe Regeln zum Schreiben der Überwachungstabelle

Startup

# 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 =

Zu diesem Zeitpunkt finden Sie eine zusätzliche Protokolldatei im Kanalverzeichnis. Geben Sie diese ein und Sie können das Hauptprotokoll des Kanals sehen Datei und das Beispielknoten-Startprotokoll. bedeutet, dass Sie erfolgreich waren. Ein großer Schritt nach vorne, die Kanalüberwachung läuft normal.

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基础教程

Das obige ist der detaillierte Inhalt vonPraktische Statistiken zum Auftragseingang (1). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen