SparkStreaming实战(数据库(NoSQL))
完全搞清楚项目需求,思考项目选项,这块就是使用的是数据库,就是HBase,因为它里面有一个非常合适的API,直接调用,即可
功能一: 今天到现在为止 实战课程 的访问量
yyyyMMdd
使用数据库来进行存储我们的统计结果
Spark Streaming吧统计结果写入到数据库里面
可视化前端根据: yyyyMMdd courseid 把数据库里面的统计结果展示出来
选择什么数据库为统计结果的存储呢?
RDBMS: MySQL、Oracle...
day course_id click_count
20171111 1 10
20171111 2 10
下一个批次数据进来以后:
NoSQL: HBase、Redis....
Hbase: 一个API就能搞定,非常方便(城市字段,这块需要键 - 值,各自相加, 在多听听项目需求吧) ==> incrementColumnValue()
20171111 + 1 ==> click_count + 下一个批次的统计结果写入到数据库中
前提:
HBase
Zookeeper
HBase
HBase表设计
创建表
create 'imooc_course_clickcount', 'info';
Rowkey设计
day_courseid
pom.xml
<!--添加scala依赖-->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<!--添加hbase-client依赖-->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.3.1</version>
</dependency>
<!--添加spark-streaming依赖-->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
如何使用Scala来操作HBase
- 先定义一个实体类 domain/ ClickLog.scala CourseClickCount.scala
ClickLog.scala
/**
* 清洗后的日志信息
* @param ip 日志访问的ip地址
* @param time 日志访问的时间
* @param courseId 日志访问的实战课程编号
* @param statusCode 日志访问的状态码
* @param referer 日志访问的referer
*/
case class ClickLog(ip: String, time: String, courseId: Int, statusCode: Int, referer: String)
CourseClickCount.scala
/**
* 实战课程点击数
* @param day_course 对应的就是HBase中的rowkey, 20171111_1
* @param click_count 对应的20171111_1的访问总数
*/
case class CourseClickCount(day_course: String, click_count: Long)
- 再定义一个访问层 dao/ CourseClickCountDAO.scala
import com.project.domain.CourseClickCount
/**
* 实战课程点击数-数据访问层)
*/
object CourseClickCountDAO {
val tableName = "imooc_course_clickcount"
val cf = "info"
val qualifer = "click_count"
/**
* 保存数据到HBase
* @param list CourseClickCount集合(要传一个集合进来)
*/
def save(list: ListBuffer[CourseClickCount]): Unit = {
}
/**
* 根据rowkey查询值
* @param day_course
* @return
*/
def count(day_course: String): Long = {
}
- 接下来需要开发HBase的工具类,来完成HBase的操作 utils/ HBaseUtils.java
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
/**
* HBase操作工具类:Java工具类建议采用单例模式封装
*/
public class HBaseUtils {
HBaseAdmin admin = null;
Configuration configuration = null;
/**
* 私有构造方法
*/
private HBaseUtils() {
configuration = new Configuration();
configuration.set("hbase.zookeeper.quorum","localhost:2181");
configuration.set("hbase.rootdir","hdfs://localhost:8020/hbase");
try {
admin = new HBaseAdmin(configuration);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 单例模式
*/
private static HBaseUtils instance = null;
public static HBaseUtils getInstance() {
if (null == instance) {
instance = new HBaseUtils();
}
return instance;
}
/**
* 根据表名获取到HTable实例
*/
public HTable getTable(String tableName) {
HTable table = null;
try {
table = new HTable(configuration, tableName);
} catch (IOException e) {
e.printStackTrace();
}
return table;
}
/**
* 添加一条记录到HBase表
* @param tableName HBase表名
* @param rowkey HBase表rowkey
* @param cf HBase表columnfamily
* @param column HBase表的列
* @param value 写入HBase表的值
*/
public void put(String tableName, String rowkey, String cf, String column, String value) {
//先拿到表名
HTable table= getTable(tableName);
//放入一个列值
Put put = new Put(Bytes.toBytes(rowkey));
//放入数据
put.add(Bytes.toBytes(cf), Bytes.toBytes(column), Bytes.toBytes(value));
//传给表,需要捕获异常,增加代码的健壮性
try {
table.put(put);
} catch (IOException e) {
e.printStackTrace();
}
}
//测试
public static void main(String[] args) {
// // 获取表名
// HTable table = HBaseUtils.getInstance().getTable("imooc_course_clickcount");
//
// System.out.println(table.getName().getNameAsString());
// 往HBase表中写入数据
String tableName = "imooc_course_clickcount";
String rowkey = "20171111_88";
String cf = "info";
String column = "click_count";
String value = "2";
HBaseUtils.getInstance().put(tableName,rowkey,cf,column,value);
}
}
- 在scala代码中调用HBase工具类,去创建属性,实现方法 dao/ CourseClickCountDAO.scala
import com.project.domain.CourseClickCount
import com.project.utils.HBaseUtils
import org.apache.hadoop.hbase.client.Get
import org.apache.hadoop.hbase.util.Bytes
import scala.collection.mutable.ListBuffer
/**
* 实战课程点击数-数据访问层(下面我们就把我们的统计结果调用dao层,写入hbase中就可以了)
*/
object CourseClickCountDAO {
val tableName = "imooc_course_clickcount"
val cf = "info"
val qualifer = "click_count"
/**
* 保存数据到HBase
* @param list CourseClickCount集合(要传一个集合进来)
*/
def save(list: ListBuffer[CourseClickCount]): Unit = {
val table = HBaseUtils.getInstance().getTable(tableName)
for (ele <- list) {
table.incrementColumnValue(Bytes.toBytes(ele.day_course),
Bytes.toBytes(cf),
Bytes.toBytes(qualifer),
ele.click_count)
}
}
/**
* 根据rowkey查询值
* @param day_course
* @return
*/
def count(day_course: String): Long = {
val table = HBaseUtils.getInstance().getTable(tableName)
val get = new Get(Bytes.toBytes(day_course))
val value = table.get(get).getValue(cf.getBytes,qualifer.getBytes)
if (value == null) {
0l
} else {
Bytes.toLong(value)
}
}
/**
* 测试可否操作HBase数据库成功---
* @param args
*/
def main(args: Array[String]): Unit = {
val list = new ListBuffer[CourseClickCount]
list.append(CourseClickCount("20171111_8", 8))
list.append(CourseClickCount("20171111_9", 9))
list.append(CourseClickCount("20171111_1", 100))
save(list)
println(s"${count("20171111_8")} : ${count("20171111_9")} : ${count("20171111_100")}")
}
}
下面我们就把我们的统计结果调用dao(访问)层,写入hbase中就可以了)
三、(功能一: )统计今天到现在为止实战课程的访问量并写入HBase中
spark/ ImoocStatStreamingApp.scala
object ImoocStatStreamingApp extends App {
//配置入口点
val conf = new SparkConf().setAppName(getClass.getSimpleName).setMaster("local[2]")
val ssc= new StreamingContext(conf, Seconds(1))
//输入数据流(DStream) (自己随便定义的,不是用这个,为了不报错)
val cleanData = ssc.textFileStream("")
//测试步骤三: 统计今天到现在为止实战课程的访问量,并把它写到HBase数据库中
cleanData.map(x => {
// HBase rowkey设计: 20171111_88
(x.time.substring(0,8)) + "_" + x.courseId, 1) // key ==> k+1
}).reduceBykey(_ + _).foreachRDD(rdd => { //用foreachRDD对DStream进行隐式转换,让它拥有RDD的方法(反射)
rdd.foreachPartition(partitionRecords => {
val list = new ListBuffer[CourseClickCount]
partitionRecords.foreach(pair => {
list.append(CourseClickCount(pair._1, pair._2))
})
CourseClickCountDAO.save(list)
})
})
//启动StreamingContext,接收数据,然后处理数据
ssc.start()
ssc.awaitTermination()
此处代码已经在本地开发测试完成,接下来,就需要打包到服务器上去执行.
四、(功能二)统计今天到现在为止从搜索引擎引流过来的实战课程的访问量
功能二: 功能一+从搜索引擎引流过来的
HBase表设计
create 'imooc_course_search_clickcount', 'info' //创建表
scan 'imooc_course_search_clickcount' // 查看内容
rowkey设计: 也是根据我们的业务需求来的
20171111 + search + 1 (rowkey设计后的格式)
代码开发:
domain/ CourseSearchClickCount.scala(数据实体类层开发)
/**
* 从搜索引擎过来的实战课程点击数实体类
* @param day_search_course
* @param click_count
*/
case class CourseSearchClickCount(day_search_course: String, click_count: Long)
DAO/ CourseSearchClickCountDAO.scala(数据访问层开发)
import com.project.domain.CourseSearchClickCount
import com.project.utils.HBaseUtils
import org.apache.hadoop.hbase.client.Get
import org.apache.hadoop.hbase.util.Bytes
import scala.collection.mutable.ListBuffer
/**
* 实战课程点击数-数据访问层(下面我们就把我们的统计结果调用dao层,写入hbase中就可以了)
*/
object CourseSearchClickCountDAO {
val tableName = "imooc_course_search_clickcount"
val cf = "info"
val qualifer = "click_count"
/**
* 保存数据到HBase
* @param list CourseSearchClickCount(要传一个集合进来)
*/
def save(list: ListBuffer[CourseSearchClickCount]): Unit = {
val table = HBaseUtils.getInstance().getTable(tableName)
for (ele <- list) {
table.incrementColumnValue(Bytes.toBytes(ele.day_search_course),
Bytes.toBytes(cf),
Bytes.toBytes(qualifer),
ele.click_count)
}
}
/**
* 根据rowkey查询值
* @param day_search_course
* @return
*/
def count(day_search_course: String): Long = {
val table = HBaseUtils.getInstance().getTable(tableName)
val get = new Get(Bytes.toBytes(day_search_course))
val value = table.get(get).getValue(cf.getBytes,qualifer.getBytes)
if (value == null) {
0l
} else {
Bytes.toLong(value)
}
}
/**
* 测试可否操作HBase数据库成功---
* @param args
*/
def main(args: Array[String]): Unit = {
val list = new ListBuffer[CourseSearchClickCount]
list.append(CourseSearchClickCount("20171111_www.baidu.com_8", 8))
list.append(CourseSearchClickCount("20171111_cn.bing.com_9", 9))
save(list)
println(s"${count("20171111_www.baidu.com_8")} : ${count("20171111_cn.bing.com_9")} ")
}
}
spark/ ImoocStatStreamingApp.scala
// 测试步骤四: 统计从搜索引擎过来的今天到现在为止实战课程的访问量
cleanData.map(x => {
/**
* https://www.sogou.com/web?query=Spark SQL实战
*
* ==>
*
* https:/www.sogou.com/web?query=Spark SQL实战
*/
val referer = x.referer.replaceAll("//", "/") //( 把 // 替换为 / )
val splits = referer.split("/") //用 / 将url分开
var host = ""
if (splits.length > 2) { //如果大于2,才说明从搜索引擎过来的
host = splits(1)
}
(host, x.courseId, x.time) //返回三个字段 元组类型
}).filter(_._1 != "") //对返回值进行操作; 如果不为空,就是从refer过来的;为空,就不是从refer过来的,过滤掉
.map(x => {
(s"${x._3.substring(0,8)}_${x._1}_${x._2} ",1) // 获取每条记录的 时间,搜索引擎,时间编号, 并给每条赋 1
}).reduceBykey(_ + _).foreachRDD(rdd => { //用foreachRDD对DStream进行隐式转换,让它拥有RDD的方法(反射)将其写入数据库中
rdd.foreachPartition(partitionRecords => {
val list = new ListBuffer[CourseSearchClickCount]
partitionRecords.foreach(pair => {
list.append(CourseSearchClickCount(pair._1, pair._2))
})
CourseSearchClickCountDAO.save(list)
})
})
注意:
测试时,预先需要在Hbase数据库中建立相应的表,便于测试
将结果打印在控制台上(在IDEA中观察结果,再到HBase数据库中查看结果,验证是否正确)
本地测试到此结束,下面开启将程序打包提交到服务器端运行.
将项目运行在服务器环境中
- 编译打包
- 运行
项目打包: $ mvn clean package -DskipTests
报错:
需要注销这两行,因为在本地进行scala调用java代码的时候,可以直接操作,
编译打包到生产上的时候,没有指向java目录中,所以需要,将下面两行注销
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory></testSourceDirecetory>
mac系统,需要使用scp去传递到生产上.
--package org.apache.spark:spark-streaming-kafka-0-8_2.11:2.2.0 \
--jars $(echo /home/hadoop/app/hbase-1.2.0-cdh5.7.0/lib/*.jar | tr ' ' ',')
// tr ' ' ',' ==》 空白处用 , 分隔 (把hbase的jar包用逗号拼起来)
- 加入高级数据源的包 spark-streaming-kafka-0-8_2.11
- 添加hbase的所有jar包
提交作业时,注意事项:
1) --packages的使用
2) --jars的使用
(将本地的项目跑到环境环境中)
mac -> linux(spark集成环境)
SparkStreaming实战(数据库(NoSQL))的更多相关文章
- 转 14 jmeter性能测试实战--数据库MySQL
14 jmeter性能测试实战--数据库MySQL 需求 测试用户表(对用户表select操作) 测试步骤 1.MySQL驱动下载并安装. 2.测试计划面板点击"浏览"按钮,将 ...
- 非关系型数据库Nosql的优缺点分析
Nosql的全称是Not Only Sql,Nosql指的是非关系型数据库,而我们常用的都是关系型数据库.就像我们常用的mysql,oralce.sqlserver等一样,这些数据库一般用来存储重要信 ...
- NoSQL数据库---NoSQL数据库的分类
NoSQL数据库的分类 个人理解一下文档型数据库: 就是键值对数据库的升级,允许键值之间嵌套键值,比如JSON格式的数据.效率比key_value的数据库更高. [更多参考]http://www.cn ...
- 学了那么多 NoSQL 数据库 NoSQL 究竟是啥
NoSQL 简史 NoSQL 一词最早出现于 1998 年,是 Carlo Strozzi 开发的一个轻量.开源.不提供 SQL 功能的关系数据库. 2009 年,Last.fm 的 Johan Os ...
- Redis 非关系型数据库 ( Nosql )
简介: Redis 是一个开源的,高性能的 key-value 系统,可以用来缓存或存储数据. Redis 数据可以持久化,并且支持多种数据类型:字符串(string),列表(list),哈希(has ...
- 2.spark-streaming实战
park Streaming--实战篇 摘要: Sprak Streaming属于Saprk API的扩展,支持实时数据流(live data streams)的可扩展,高吞吐(hight- ...
- 非关系型数据库(NOSQL)-Redis
整理一波Redis 简介,与memcached比较 官网:http://redis.io Redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括 ...
- Hapi+MySql项目实战数据库操作(四)
数据库访问 下面以Node的ORM框架Sequelize来操作数据库,Mysql为例. 配置数据库连接信息config/db_config.js: //db_config.js module.expo ...
- 14 jmeter性能测试实战--数据库MySQL
需求 测试用户表(对用户表select操作) 测试步骤 1.MySQL驱动下载并安装. 2.测试计划面板点击“浏览”按钮,将JDBC驱动(mysql-connector-java.jar)添加进来. ...
随机推荐
- SQL注入漏洞技术的详解
SQL注入漏洞详解 目录 SQL注入的分类 判断是否存在SQL注入 一:Boolean盲注 二:union 注入 三:文件读写 四:报错注入 floor报错注入 ExtractValue报错注入 Up ...
- docker 简单介绍与安装
主机虚拟化(vmware,visual box等) type-Ⅰ type=Ⅱ 主机虚拟化是隔离最彻底的,但是由于多隔了一个虚拟的操作系统,性能会慢一些. 容器虚拟化(docker等) 隔离没有主机虚 ...
- JavaScript判断是否是数字
JavaScript判断是否是数字的几种方法 isNaN() /** * 判断是否是数字 */ function isNumber(value){ if(isNaN(value)){ return f ...
- fiddler---Fiddler工具栏功能介绍
前几篇简单的介绍了Fiddler的功能,对于工具栏的操作只是简单了解,今天写一篇工具栏功能介绍和操作. 工具栏功能介绍 工具栏内容 工具栏依次是:会话保存,数据重放(Replay),转到(GO),数据 ...
- 史上最全的LaTeX特殊符号语法
史上最全的LaTeX特殊符号语法 运算符 语法 效果 语法 效果 语法 效果 + \(+\) - \(-\) \triangleleft \(\triangleleft\) \pm \(\pm\) \ ...
- 工具资源系列之给 windows 虚拟机装个 centos
前面我们已经介绍了如何在 Windows 宿主机安装 VMware 虚拟机,这节我们将利用安装好的 VMware 软件安装 centos 系统. 前情回顾 由于大多数人使用的 Windows 电脑而工 ...
- dirb参数解析
-----------------DIRB v2.22 By The Dark Raver----------------- dirb <url_base> [<wordlist_f ...
- Mac操作:Mac系统移动鼠标显示桌面(移动鼠标到角落)
很多朋友都发现,有的人在用Mac的时候,鼠标一划就可以显示桌面,或者显示Launchpad.其实很简单,下面就介绍这个方法. 首先打开系统偏好设置: 然后点击红色圈中的图标:MissionContro ...
- Appium swipe实现屏幕滑动
在 Appium 中提供 swipe() 方法来模拟用户滑动屏幕. swipe() 实现过程 是先通过在屏幕上标记两个坐标,然后再从开始坐标移动到结束坐标. 先看下 swipe 方法定义: def s ...
- 未初始化内存检测(MSan)
https://github.com/google/sanitizers/wiki https://github.com/google/sanitizers/wiki/MemorySanitizer ...