随着人口红利的慢慢削减,互联网产品的厮杀愈加激烈,大家开始看好下沉市场的潜力,拼多多,趣头条等厂商通过拉新奖励,购物优惠等政策率先抢占用户,壮大起来。其他各厂商也紧随其后,纷纷推出自己产品的极速版,如今日头条极速版,腾讯新闻极速版等,也通过拉新奖励,阅读奖励等政策来吸引用户。

对于这类APP,实时风控是必不可少的,一个比较常见的实时风控场景就是防刷接口作弊。刷接口是黑产的一种作弊手段,APP上的各种操作,一般都会对应后台的某个接口,用户操作APP数据就会通过接口上报到后台,但如果黑产通过破解获取到了APP的新增用户接口,那他们就能跳过登陆APP步骤直接调后台接口构造虚假数据牟利了。对于这类业务,我们可以通过Flink + Redis来实现实时防刷接口的功能。数据流图如下所示:



刷接口作弊一般是越过登陆APP操作,直接调Server端的接口发数据,这些用户在APP的上报日志里面就不存在,那我们可以通过Flink将APP实时上报上来的新增用户写入Redis中,然后Server端将接口上报上来的用户与Redis里的用户进行比对,如果不在Redis里面则判为刷接口用户。

对于这个需求,得要求实时计算引擎能达到毫秒级延迟,否则会造成用户的误判和影响用户体验。为此我们选择了Flink作为实时计算引擎。

主要代码逻辑如下:

//配置flink运行环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
//val env = StreamExecutionEnvironment.createLocalEnvironment()
env.enableCheckpointing(1000 * 60 * 5)
env.getCheckpointConfig.setCheckpointingMode(CheckpointingMode.AT_LEAST_ONCE)
env.getCheckpointConfig.setMinPauseBetweenCheckpoints(1000 * 60 * 3)
env.getCheckpointConfig.setMaxConcurrentCheckpoints(1)
env.setStateBackend(new FsStateBackend(checkPointPath))
env.getConfig.setLatencyTrackingInterval(1000)
env.getConfig.registerTypeWithKryoSerializer(classOf[Log], classOf[ProtobufSerializer])
env.setStreamTimeCharacteristic(EventTime)
env.setParallelism(parallel)
env.getConfig.setLatencyTrackingInterval(1000) //kafka source,实时消费kafka中日志解析出用户id
val stream = env.addSource(new FlinkKafkaConsumer010[Array[Log]](topic, new LogDeserializationSchema(), properties))
val data = stream.flatMap(x => x)
.map(log =>{
val userid = log.getUid.getUuid
val current_time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
(userid,current_time)
}).filter(record=>{
val userid = record._1
var flag = false
if(userid != null && !"".equals(userid)){
flag = true
}
flag
}) //redis sink,将APP上报日志的用户id写入redis供server端匹配
data.addSink(new RedisSink[(String, String)](getJedisClusterConfig, new RedisSinkMapper))
env.execute("newsinfo_active_userid_to_redis")

其中比较重要的几点:

1 构造kafka source

val stream = env.addSource(new FlinkKafkaConsumer010[Array[Log]](topic, new LogDeserializationSchema(), properties))

一般APP上报的都是序列化的数据,我们需要定义反序列化方法,LogDeserializationSchema 是一个protobuf类型的反序列化方法。

//将kafka中的数据解析为google protobuf 的Log,一个message可能包含多条Log
class LogDeserializationSchema extends AbstractDeserializationSchema[Array[Log]] {
override def deserialize(message: Array[Byte]): Array[Log] = {
val data = ArrayBuffer[Log]()
val input = new ByteArrayInputStream(message)
while (input.available() > 0) {
try {
data += Log.parseDelimitedFrom(input)
} catch {
case _: Throwable =>
}
}
input.close()
data.toArray
}
}

2 redis sink

这里用的是网上开源的flink-connector-redis依赖库。

更多相关内容见:http://bahir.apache.org/docs/flink/current/flink-streaming-redis

Maven依赖如下

<dependency>
<groupId>org.apache.bahir</groupId>
<artifactId>flink-connector-redis_2.11</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>

Redis Sink 提供用于向Redis发送数据的接口的类。接收器可以使用三种不同的方法与不同类型的Redis环境进行通信:

  • 单Redis服务器
  • Redis集群
  • Redis Sentinel

Redis Sink 核心类是 RedisMappe 是一个接口,使用时我们要编写自己的redis操作类实现这个接口中的三个方法,如下所示:

class RedisExampleMapper extends RedisMapper[(String, String)]{
override def getCommandDescription: RedisCommandDescription = {
new RedisCommandDescription(RedisCommand.HSET, "HASH_NAME")
} override def getKeyFromData(data: (String, String)): String = data._1 override def getValueFromData(data: (String, String)): String = data._2
}
val conf = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").build()
stream.addSink(new RedisSink[(String, String)](conf, new RedisExampleMapper))

使用RedisCommand设置数据结构类型时和redis结构对应关系。

以上我们利用 Flink + Redis 实时了一个基本的实时防刷接口模型。关注微信公众号《大数据技术进阶》,观看更多大数据实战文章。

Flink实战| Flink+Redis实时防刷接口作弊的更多相关文章

  1. 使用Redis 计数器防止刷接口

    业务需求中经常有需要用到计数器的场景:为了防止恶意刷接口,需要设置一个接口每个IP一分钟.一天等的调用次数阈值:为了降低费用,限制发送短信的次数等.使用Redis的Incr自增命令可以轻松实现以上需求 ...

  2. 使用Redis+自定义注解实现接口防刷

    最近开发了一个功能,需要发送短信验证码鉴权,考虑到短信服务需要收费,因此对此接口做了防刷处理,实现方式主要是Redis+自定义注解(需要导入Redis的相关依赖,完成Redis的相关配置,gs代码,这 ...

  3. spring boot 对某个接口进行次数限制,防刷。简易版。demo。

    一般的项目 如果没有做防刷 容易被人爆接口 或者就是说没有做token防刷过滤. 容易被人用正常的token刷接口.有些token非一次性. 用户登录之后生成token会有一个过期时间,但一般没有做频 ...

  4. spring中实现基于注解实现动态的接口限流防刷

    本文将介绍在spring项目中自定义注解,借助redis实现接口的限流 自定义注解类 import java.lang.annotation.ElementType; import java.lang ...

  5. Flink + 强化学习 搭建实时推荐系统

    如今的推荐系统,对于实时性的要求越来越高,实时推荐的流程大致可以概括为这样: 推荐系统对于用户的请求产生推荐,用户对推荐结果作出反馈 (购买/点击/离开等等),推荐系统再根据用户反馈作出新的推荐.这个 ...

  6. 通过Redis、Memcache的 incr 原子操作防刷机制的使用差别

    我的版本如下: Redis:3.2.100 Memcache:1.4.4 最近在处理服务器压力测试的时候,想到一个方案,在一定时间段内限制用户访问次数.具体的实现就是通过redis的院子操作incre ...

  7. Spring Boot项目的接口防刷

    说明:使用了注解的方式进行对接口防刷的功能,非常高大上,本文章仅供参考 一,技术要点:springboot的基本知识,redis基本操作, 首先是写一个注解类: import java.lang.an ...

  8. Jmeter实时监控+SpringBoot接口性能实战

    性能测试 Jmeter实时监控+SpringBoot接口性能实战 自动化 SpringBoot Java Jmeter实时监控+SpringBoot接口性能实战 一.实验目的及实验环境 1.1.实验目 ...

  9. Spring Boot 项目的 API 接口防刷

    首先是写一个注解类 拦截器中实现 注册到springboot中 在Controller中加入注解 说明:使用了注解的方式进行对接口防刷的功能,非常高大上,本文章仅供参考 一,技术要点:springbo ...

随机推荐

  1. DirectX12 3D 游戏开发与实战第二章内容

    矩阵代数 学习目标 理解矩阵及其相关运算的定义 探究为何能把向量和矩阵的乘法视为一种线性组合 学习单位矩阵.转置矩阵.行列式以及矩阵的逆等概念 逐步熟悉DirectXMath库中提供的关于矩阵计算的类 ...

  2. charles 访问控制设置

    本文参考:charles 访问控制设置 charles 访问控制设置 access control settings 访问账户设置: 这里可以配置连接到charles时的一些配置: 这个访问控制确定谁 ...

  3. 【linux】【sonarqube】安装sonarqube7.9

    前言 SonarQube 是一款用于代码质量管理的开源工具,它主要用于管理源代码的质量. 通过插件形式,可以支持众多计算机语言,比如 java, C#, go,C/C++, PL/SQL, Cobol ...

  4. 浅谈Linux进程管理

    一  查看系统进程 在linux中,查看系统进程的命令为ps,常用格式为如下两个: (1)ps aux:unix格式查看系统进程 (2)ps -le:linux格式查看系统进程 一般地,ps aux更 ...

  5. python语言程序设计基础 习题 天天向上的力量(math.pow)

    实例1: 一年365天,,以第一天的能力值为基数1.0,当好好学习时能力值相比前一天提高1%,没有学习时能力值相比前天要降低1%,每天努力和每天放任,一年下来的能力值相差多少? 解析: 如果每天都好好 ...

  6. 使用Storm实现累加求和操作

    package com.csylh; import org.apache.storm.Config; import org.apache.storm.LocalCluster; import org. ...

  7. 命名对象继承1-验证Create*命名对象安全属性的传递

    windows核心编程 第5版 48页 下半部写道 进程B调用CreateMutex时,它会向函数传递安全属性信息和第二参数.如果已经存在一个指定名称的对象,这些对象就会被忽略 于是我通过代码来验证这 ...

  8. 【SQL server初级】SQL Server 2005 实现数据库同步备份 过程--结果---分析

    数据库复制:   简单来说,数据库复制就是由两台服务器,主服务器和备份服务器,主服务器修改后,备份服务器自动修改. 复制的模式有两种:推送模式和请求模式,推送模式是主服务器修改后,自动发给备份服务器, ...

  9. flexible.js分析--JavaScript

    //立即执行函数 (function flexible(window, document) { // 获取的html 的根元素 var docEl = document.documentElement ...

  10. .NET成人礼 | 还记得20年前一起拖过的控件吗?

    本文是MVP Ediwang写的回忆一个80后的拖控件的感悟,与君共勉: 每一代人都有记忆里的味道.煤球炉.黑白电视机是属于父母的记忆.而“拖控件”式编程,启蒙了无数像我这样的80后(嗯,89也算80 ...