# Spark实战--寻找5亿次访问中，访问次数最多的人

·  阅读 2232

## 问题描述

• 1、用户的id
• 2、用户访问的时间
• 3、用户逗留的时间
• 4、用户执行的操作
• 5、用户的其余数据（比如IP等等）

## 问题分析

5亿条ID数据，首先可以用map将其缓存到RDD中，然后对RDD进行reduceByKey，最后找出出现最多的ID。思路很简单，因此代码量也不会很多

## 实现

### scala实现

RandomId.class

``````import scala.Serializable;

public class RandomId implements Serializable {

private static final long twist(long u, long v) {
return (((u & 0x80000000L) | (v & 0x7fffffffL)) >> 1) ^ ((v & 1) == 1 ? 0x9908b0dfL : 0);
}
private long[] state= new long[624];
private int left = 1;
public RandomId() {
for (int j = 1; j < 624; j++) {
state[j] = (1812433253L * (state[j - 1] ^ (state[j - 1] >> 30)) + j);
state[j] &= 0xfffffffffL;
}
}
public void next_state() {
int p = 0;
left = 624;
for (int j = 228; --j > 0; p++)
state[p] = state[p+397] ^ twist(state[p], state[p + 1]);

for (int j=397;--j>0;p++)
state[p] = state[p-227] ^ twist(state[p], state[p + 1]);

state[p] = state[p-227] ^ twist(state[p], state[0]);
}

public long next() {
if (--left == 0) next_state();
return state[624-left];
}

}

``````

``````import org.apache.spark.{SparkConf, SparkContext}

object ActiveVisitor {

def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("spark://master:7077").setAppName("ActiveVisitor")

val sc = new SparkContext(conf)

val list = 1 until 100000

val id =new RandomId()

var max = 0

var maxId = 0L

val lastNum = sc.parallelize(list).flatMap(num => {
var list2 = List(id.next())
for (i <- 1 to 50000){
list2 = id.next() :: list2
}
println(num +"%")
list2
}).map((_,1)).reduceByKey(_+_).foreach(x => {
if (x._2 > max){
max = x._2
maxId = x._1
println(x)
}
})
}

}
``````

``````import org.apache.spark.{SparkConf, SparkContext}

object ActiveVisitor {

def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("spark://master:7077").setAppName("ActiveVisitor")

val sc = new SparkContext(conf)

//生成一个0-9999的列表
val list = 1 until 10000

val id =new RandomId()

//这里记录最大的次数
var max = 0

//这里记录最大次数的ID
var maxId = 0L

val lastNum = sc.parallelize(list)
//第一步生成5亿条数据
.flatMap(num => {
//遍历list列表
//总共遍历1万次每次生成5万个ID
var list2 = List(id.next())
for (i <- 1 to 50000){
list2 = id.next() :: list2
}
//这里记录当前生成ID的百分比
println(num/1000.0 +"%")

//返回生成完成后的list
//每次循环里面都包含5万个ID
list2
})
//遍历5亿条数据
//为每条数据出现标记1
.map((_,1))
//对标记后的数据进行处理
//得到每个ID出现的次数，即（ID，Count）
.reduceByKey(_+_)
//遍历处理后的数据
.foreach(x => {
//将最大值存储在max中
if (x._2 > max){
max = x._2
maxId = x._1
//若X比之前记录的值大，则输出该id和次数
//最后一次输出结果，则是出现次数最多的的ID和以及其出现的次数
//当然出现次数最多的可能有多个ID
//这里只输出一个
println(x)
}
})
}

}

``````

## 运行得到结果

``````1%
5000%
2%
5001%
3%
5002%
4%
5003%
5%
5004%
6%
5005%
7%
5006%
8%
5007%
9%
5008%
10%
5009%
11%
5010%
12%
5011%
5012%
13%
5013%
14%
15%
5014%

...
...
...

``````

``````5634%
5635%
5636%
5637%
5638%
5639%
5640%
5641%
5642%
5643%
5644%
5645%
2019-03-05 11:52:14 INFO  ExternalSorter:54 - Thread 63 spilling in-memory map of 1007.3 MB to disk (2 times so far)
647%
648%
649%
650%
651%
652%
653%
654%
655%
656%
``````

## 结果

``````import org.apache.spark.{SparkConf, SparkContext}

object ActiveVisitor {

def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("spark://master:7077").setAppName("ActiveVisitor")

val sc = new SparkContext(conf)

//生成一个0-9999的列表
val list = 1 until 10000

val id =new RandomId()

//这里记录最大的次数
var max = 0

//这里记录最大次数的ID
var maxId = 0L

val lastNum = sc.parallelize(list)
//第一步生成5亿条数据
.flatMap(num => {
//遍历list列表
//总共遍历1万次每次生成5万个ID
var list2 = List(id.next())
for (i <- 1 to 50000){
list2 = id.next() :: list2
}
//这里记录当前生成ID的百分比
println(num/1000.0 +"%")

//返回生成完成后的list
//每次循环里面都包含5万个ID
list2
})
//遍历5亿条数据
//为每条数据出现标记1
.map((_,1))
//对标记后的数据进行处理
//得到每个ID出现的次数，即（ID，Count）
.reduceByKey(_+_)
//为数据进行排序
//倒序
.sortByKey(false)

//次数最多的，在第一个，将其输出
println(lastNum.first())
}

}
``````