〇、概述

1、实现内容

使用Scala编写代码,通过Flink的Source、Sink以及时间语义实现实时销量展示

2、过程

(1)导包并下载依赖

(2)创建数据源数据表并写⼊数据

(3)在Mysql数据库中创建统计结果表

(4)编写Flink计算代码

a.参考ShopMysqlSource.scala 代码,进⾏Flink Source 编写,从Mysql读取数据

b.参考GaotuShopFlinkStat.scala代码,进⾏统计逻辑的编写,进⾏FlinkSQL 查询

c.参考ShopStatMysqlSink.scala 代码,进⾏FlinkSink 编写,存⼊数据到Mysql

一、导包并下载依赖

二、创建数据源数据表并写⼊数据

参考执⾏GenerateOrders.scala 代码

package com.gaotu.flink
import org.apache.commons.lang.time.FastDateFormat import java.sql.DriverManager
import java.sql.Connection
import java.util.concurrent.TimeUnit
import scala.util.Random /**
* 向Mysql数据库中添加数据
* CREATE TABLE `g_orders` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '交易id',
`stock_name` varchar(20)DEFAULT NULL COMMENT '商品名称',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`deal_status` varchar(20) DEFAULT NULL COMMENT '交易状态',
`stock_cnt` int(11) DEFAULT NULL COMMENT '商品数量',
`deal_amount` double DEFAULT NULL COMMENT '订单金额',
`oper_time` bigint COMMENT '处理时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8;
*
*/
object GenerateOrders { def main(args: Array[String]): Unit = {
val driver = "com.mysql.cj.jdbc.Driver"
val url = "jdbc:mysql://localhost/plato"
val username = "root"
val password = "root"
var connection:Connection = null //商品数组
val stocks = Array("HUAWEI Mate40","Apple iphone13","Apple MacBook Pro 14"
,"ThinkBook 14p","RedmiBook Pro14","飞鹤星飞帆幼儿奶粉","爱他美 幼儿奶粉"
,"李宁运动男卫裤","小米踏步机椭圆机","欧莱雅面膜","御泥坊面膜","欧莱雅男士套装","金六福白酒"
,"牛栏山42度","茅台飞天")
val amount = Array(6569.00,6099.00,14999.00,6799.00,4899.00,275,392,199,1299.00,599,399,389,469,175,1399.00) try {
Class.forName(driver)
connection = DriverManager.getConnection(url, username, password)
val ps = connection.createStatement()
for (i <- 1 to 10000){
val formater = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
val item = scala.util.Random.nextInt(14)
val deal_time = formater.format(System.currentTimeMillis())
val stock_name = stocks(item)
val user_id = Random.nextInt(100)
val deal_status = "有效"
val stock_cnt = Random.nextInt(20)
val deal_amount = amount(item)
val oper_time = System.currentTimeMillis()
val query = s"insert into g_orders(deal_time,stock_name,user_id,deal_status,stock_cnt,deal_amount,oper_time) values('$deal_time', '$stock_name', $user_id, '$deal_status', $stock_cnt, $deal_amount, $oper_time)"
ps.addBatch(query)
println(query) TimeUnit.SECONDS.sleep(1)
}
ps.executeBatch()
} catch {
case e => e.printStackTrace
}
connection.close()
}
}

三、在Mysql数据库中创建统计结果表

-- 统计结果表 
CREATE TABLE `g_orders_stat` (
`stock_name` varchar(20)DEFAULT NULL COMMENT '商品名称',
`order_cnt` int(11) DEFAULT NULL COMMENT '商品数量',
`stock_sales_cnt` int(11) DEFAULT NULL COMMENT '商品数量',
`stock_sales_amt` double DEFAULT NULL COMMENT '商品数量'
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8;

四、编写Flink计算代码

1、参考ShopMysqlSource.scala 代码,进⾏Flink Source 编写,从Mysql读取数据

package com.gaotu.flink

import org.apache.flink.streaming.api.functions.source.RichSourceFunction
import org.apache.flink.streaming.api.functions.source.SourceFunction.SourceContext
import java.sql.{Connection, DriverManager, PreparedStatement}
import java.util.concurrent.TimeUnit /*
* Mysql Source
*/
class ShopMysqlSource extends RichSourceFunction[(Int, String, Int, Double, Long)] {
val driver = "com.mysql.cj.jdbc.Driver"
val url = "jdbc:mysql://localhost/plato"
val username = "root"
val password = "root" override def run(ctx: SourceContext[(Int, String, Int, Double, Long)]): Unit = {
// 1. 加载MYSQL驱动
Class.forName(driver)
// 2. 建立MYSQL链接
var connection: Connection = DriverManager.getConnection(url, username, password)
var max_id = 0
// 3. 创建PreparedStatement
val sql = s"select id,stock_name,stock_cnt,deal_amount,oper_time from plato.g_orders where id > ${max_id} ;"
// 4. 执行Sql查询
val ps: PreparedStatement = connection.prepareStatement(sql)
for(i <- 0 until 500) {
val queryRequest = ps.executeQuery()
// 5. 遍历结果
while (queryRequest.next()) {
val id = queryRequest.getInt("id")
val stock_name = queryRequest.getString("stock_name")
val stock_cnt = queryRequest.getInt("stock_cnt")
val deal_amount = queryRequest.getDouble("deal_amount")
val deal_time = queryRequest.getLong("oper_time")
ctx.collect((id, stock_name, stock_cnt, deal_amount, deal_time)) if(max_id < id){
max_id = id
}
}
TimeUnit.SECONDS.sleep(1)
}
}
override def cancel(): Unit = {}
}

2、参考GaotuShopFlinkStat.scala代码,进⾏统计逻辑的编写,进⾏FlinkSQL 查询

package com.gaotu.flink

import org.apache.flink.api.scala._
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks
import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}
import org.apache.flink.streaming.api.watermark.Watermark
import org.apache.flink.table.api.{Table, TableEnvironment}
import org.apache.flink.table.api.scala._ /**
* 实时统计逻辑
*/
object GaotuShopFlinkStat { def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment // 1.创建流处理环境
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) // 2.设置处理时间为事件
val tableEnv = TableEnvironment.getTableEnvironment(env) // 3.获取Table运行环境
val orderDataStream = env.addSource(new ShopMysqlSource) // 4.获取自定义数据源
// 5.添加水印,允许延迟2秒
val watermarkDataStream:DataStream[(Int, String, Int, Double, Long)] = orderDataStream.assignTimestampsAndWatermarks(
new AssignerWithPeriodicWatermarks[(Int, String, Int, Double, Long)]{
var currentTimestamp: Long = _
val delayTime = 2000 // 允许延迟2秒
override def getCurrentWatermark: Watermark = { // 生成一个水印时间
val watermark = new Watermark(currentTimestamp - delayTime) // 让时间窗口延迟2秒计算
watermark
}
// 从订单中获取对应的时间戳
override def extractTimestamp(element: (Int, String, Int, Double, Long), previousElementTimestamp: Long): Long = {
val oper_time = element._5 // 获取订单的事件时间(下单时的时间)
currentTimestamp = Math.max(currentTimestamp, oper_time) // 当前时间与事件时间对比,获取最大值
currentTimestamp
}
} ) // 6.注册LinkSQL数据表
tableEnv.registerDataStream("g_order", watermarkDataStream, 'id,'stock_name,'stock_cnt,'deal_amount,'oper_time,'createTime.rowtime)
// 7.编写SQL语句进行统计
val sql =
"""
| select
| stock_name
| ,count(id) as order_cnt
| ,sum(stock_cnt) as stock_sales_cnt
| ,sum(deal_amount) as stock_sales_amt
| from g_order
| group by
| tumble(createTime, interval '5' second ),
| stock_name
|""".stripMargin
// 8.执行sql语句
val table: Table = tableEnv.sqlQuery(sql)
table.printSchema() // 9.将SQL的执行结果写入到Mysql中
tableEnv.toAppendStream[(String, Long, Int, Double)](table).addSink(new ShopStatMysqlSink)
// 10.执行任务
env.execute()
}
}

3、参考ShopStatMysqlSink.scala 代码,进⾏FlinkSink 编写,存⼊数据到Mysql

package com.gaotu.flink

import org.apache.flink.configuration.Configuration
import org.apache.flink.streaming.api.functions.sink.RichSinkFunction
import java.sql.{Connection, DriverManager, PreparedStatement} /**
* Mysql Sink
*
* CREATE TABLE `g_orders_stat` (
`stock_name` varchar(20)DEFAULT NULL COMMENT '商品名称',
`order_cnt` int(11) DEFAULT NULL COMMENT '商品数量',
`stock_sales_cnt` int(11) DEFAULT NULL COMMENT '商品数量',
`stock_sales_amt` double DEFAULT NULL COMMENT '商品数量'
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8;
*
*/
class ShopStatMysqlSink extends RichSinkFunction[(String, Long, Int, Double)] { val driver = "com.mysql.cj.jdbc.Driver"
val url = "jdbc:mysql://localhost/plato"
val username = "root"
val password = "root"
var connection: Connection = null
var ps: PreparedStatement = null override def open(parameters: Configuration): Unit = {
Class.forName(driver) // 1. 加载驱动
connection = DriverManager.getConnection(url, username, password) // 2. 创建连接
val sql = "insert into g_orders_stat (stock_name,order_cnt,stock_sales_cnt,stock_sales_amt) values (?,?,?,?);" // 3. 获得执行语句
ps = connection.prepareStatement(sql)
}
override def invoke(value: (String, Long, Int, Double)): Unit = {// 4. 插入数据
try {
ps.setString(1, value._1)
ps.setLong(2, value._2)
ps.setInt(3, value._3)
ps.setDouble(4, value._4)
ps.execute()
} catch {
case e: Exception => println(e.getMessage)
}
}
// 5. 关闭连接操作
override def close(): Unit = {
if(connection != null) {
connection.close()
}
if(ps != null) {
ps.close()
}
}
}

【大数据课程】高途课程实践-Day03:Scala实现商品实时销售统计的更多相关文章

  1. MySQL在大数据、高并发场景下的SQL语句优化和"最佳实践"

    本文主要针对中小型应用或网站,重点探讨日常程序开发中SQL语句的优化问题,所谓“大数据”.“高并发”仅针对中小型应用而言,专业的数据库运维大神请无视.以下实践为个人在实际开发工作中,针对相对“大数据” ...

  2. WOT干货大放送:大数据架构发展趋势及探索实践分享

      WOT大数据处理技术分会场,PingCAP CTO黄东旭.易观智库CTO郭炜.Mob开发者服务平台技术副总监林荣波.宜信技术研发中心高级架构师王东及商助科技(99Click)顾问总监郑泉五位讲师, ...

  3. 大数据量高并发的数据库优化详解(MSSQL)

    转载自:http://www.jb51.net/article/71041.htm 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能. ...

  4. 网易大数据平台的Spark技术实践

    网易大数据平台的Spark技术实践 作者 王健宗 网易的实时计算需求 对于大多数的大数据而言,实时性是其所应具备的重要属性,信息的到达和获取应满足实时性的要求,而信息的价值需在其到达那刻展现才能利益最 ...

  5. 王家林的81门一站式云计算分布式大数据&移动互联网解决方案课程第14门课程:Android软硬整合设计与框架揭秘: HAL&Framework &Native Service &App&HTML5架构设计与实战开发

    掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime ...

  6. IT大数据服务管理高级课程(IT服务,大数据,云计算,智能城市)

    个人简历 金石先生是马克思主义中国化的研究学者,上海财经大学经济学和管理学硕士,中国民主建国会成员,中国特色社会主义人文科技管理哲学的理论奠基人之一.金石先生博学多才,对问题有独到见解.专于工作且乐于 ...

  7. 大数据量高并发的数据库优化,sql查询优化

    一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...

  8. DB开发之大数据量高并发的数据库优化

    一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...

  9. 大数据量高并发访问SQL优化方法

    保证在实现功能的基础上,尽量减少对数据库的访问次数:通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担:能够分开的操作尽量分开处理,提高每次的响应速度:在数据窗口使用SQL时,尽量把 ...

  10. windows下大数据开发环境搭建(3)——Scala环境搭建

    一.所需环境 ·Java 8   二.下载Scala https://www.scala-lang.org/download/ 三.配置环境变量 SCALA_HOME: C:\scala Path: ...

随机推荐

  1. 微服务系列之Api文档 swagger整合

    1.前言 微服务架构随之而来的前后端彻底分离,且服务众多,无论是前后端对接亦或是产品.运营翻看,一个现代化.规范化.可视化.可尝试的文档是多么重要,所以我们这节就说说swagger. Swagger是 ...

  2. ProxySQL SQL 注入引擎

    ProxySQL 2.0.9 引入了 libsqlinjection 作为识别可能的 SQL 注入攻击的机制. 启用 S​​QL 注入检测 要启用 SQL 注入检测,只需要启用变量 mysql-aut ...

  3. ProxySQL配置之MySQL服务器配置

    备注:文章编写时间201904-201905期间,后续官方在github的更新没有被写入 MySQL服务器配置 [MySQL Server Configuration] 一.在ProxySQL中配置后 ...

  4. kibana知识点

    1.Kibana 有 Linux.Darwin 和 Windows 版本的安装包.由于 Kibana 基于 Node.js 运行,我们在这些平台上包含了一些必要的 Node.js 二进制文件.Kiba ...

  5. CentOS7下yum安装GitLab-CE

    前提准备 建立git用户 useradd git 关闭防火墙 systemctl stop firewalld systemctl disable firewalld 安装依赖库 yum instal ...

  6. 通过使用nginx来实现logstash的负载均衡

    文章转载自:https://blog.csdn.net/UbuntuTouch/article/details/106813223 总结: nginx配置,192.168.0.5 user nginx ...

  7. sql limit函数

    select * from <表名> order by <列名> desc limit <第几位数>; select * from villa_info order ...

  8. python今日分享(内置方法)

    目录 一.习题详解 二.数据类型的内置方法理论 三.整型相关操作 四.浮点型相关操作 五.字符串相关操作 六.列表相关操作 今日详解 一.习题详解 1.计算1-100所有数据之和 all_num = ...

  9. HTTPS涉及的加密算法讲解

    前言 从2015年左右开始,Google.Baidu.Facebook 等互联网巨头,不谋而合地开始大力推行 HTTPS, 国内外的大型互联网公司很多也都已经启用了全站 HTTPS 为鼓励全球网站的 ...

  10. getColumnName 和 getColumnLabel 的区别

    select id as user from * getColumnName返回:"id" getColumnLabel 返回:"user"