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

对于这类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. Elastic Stack 笔记(四)Elasticsearch5.6 索引及文档管理

    博客地址:http://www.moonxy.com 一.前言 在 Elasticsearch 中,对文档进行索引等操作时,既可以通过 RESTful 接口进行操作,也可以通过 Java 也可以通过 ...

  2. 上手Dubbo之 环境搭建

    和传统ssm整合--写XML配置文件 搭建服务的提供者和服务的消费者,实现服务消费者跨应用远程调用服务提供者 公共模块抽取 公共模块的抽取 服务的消费者远程调用服务的提供者, 最起码他自己要得到在服务 ...

  3. jdk1.8源码阅读

    一.java.lang java的基础类 1.object 所有类的爸爸 registerNatives() Class<?> getClass():返回运行时的类 int hashCod ...

  4. select2的多选下拉框上传

    1.加入multiple: true,属性实现多选下拉框样式 2.下拉框选择后的值是数组类型不要经过数据处理才能进行表单提交 提交的时候原下拉框所在的标签不提交,而是将多选后的值存入页面中的一个隐藏标 ...

  5. [AWS] 02 - Pipeline on EMR

    Data Analysis with EMR. Video demo: Run Spark Application(Scala) on Amazon EMR (Elastic MapReduce) c ...

  6. Java面向对象笔记(五分钟秒懂)

    面向对象概念 面向对象三大特征:封装,继承,多态 面向对象编程(OOP,Object Oriented Programing)是相对于面向过程编程说的,之前写的代码基本都是纯的面向过程编程的,当项目复 ...

  7. Android之SOAP协议与WebService服务器交互,解决超时的问题

    网络搜索大部分不能实际解决问题.特意将解决方法写下.创建MyAndroidHttpTransport 类 , package com.example.omhandroid.lib; import or ...

  8. AppBoxFuture: Raft快照及日志截断回收

      AppBoxFuture的存储引擎依赖Raft一致性协议来保证各个分区副本的一致性,如果不处理Raft日志将不断增长,因此需要特定的机制(定期或每处理一定数量的日志)来回收那些无用的日志数据.通过 ...

  9. js 判断字符串是否存在某个字符串

    可使用String和Regexp对象的相关方法进行处理,如下 一.String对象方法 1.使用indexOf()方法,返回某个指定的字符串值在字符串中首次出现的位置.如果要检索的字符串值没有出现,则 ...

  10. Linux 文件或文件夹重命名命令mv

    使用命令mv既可以重命名,又可以移动文件或文件夹.例如: 1.将目录A重命名为B mv A B 2.将/a目录移动到/b下,并重命名为c mv /a /b/c 3.将一个名为abc的文件重命名为123 ...