Redis如何实现刷票过滤

2025-03-21 02:50
文章标签 redis 刷票 过滤 实现

本文主要是介绍Redis如何实现刷票过滤,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Redis如何实现刷票过滤》:本文主要介绍Redis如何实现刷票过滤问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教...

引言

随着互联网的不断发展,网站或APP的用户流量增加,也衍生出了一些恶意刷量等问题,给数据分析及运营带来极大的困难,出现的刷票问题更是造成了严重的经济损失,所以网站或APP对恶意刷票进行过滤是十分必要的。

Redis提供了很好的解决方案,其提供的内存存储和Key-Value的存储结构,能够高效地实现刷票过滤。

本文主要介绍如何使用SpringBoot和Redis实现刷票过滤,自定义同一IP每天刷票不得超过次数。

一、概述

本文主要php分为以下几个模块:

  • 1.开发环境
  • 2.使用Redis存储数据
  • 3.使用SpringBoot开发应用
  • 4.实现同一IP每天刷票不得超过次数

二、技术选型

  • SpringBoot2.2.5.RELEASE
  • Spring5.2.4.RELEASE
  • JDK8
  • Redis

三、搭建开发环境

  • 1.安装JDK8
  • 2.安装Redis(版本不限,最好使用稳定版)
  • 3.新建SpringBoot项目

使用IDEA新建SpringBoot项目

四、使用Redis存储数据

1. 在pom.XML中加入Redis依赖

<dependency>
	<grwww.chinasem.cnoupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.在application.yml中配置Redis:

spring:
  redis:
    host: 127.0.0.1
    port: 6379

3. 在RedisConfig.Java中配置RedisTemplate和StringRedisTemplate

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory){
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
        return stringRedisTemplate;
    }
}

四、使用SpringBoot开发应用

1.在pom.xml中加入SpringBoot依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2.新建Controller

@RestController
@RequestMapping("/vote")
public class VoteController {

    private final StringRedisTemplate redisTemplate;

    public VoteController(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 投票接口
     * @param ip
     * @return
     */
    @PostMapping("/submit")
    public String submit(@RequestParam String ip){

        String key = "ip:" + ip;

        // 先判断是否已经投票,如果已经投票,则返回
        if(redisTemplate.opsForValue().get(key) != null){
            return "您已经投过票了!";
        }

        // 获取当天的日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date = sdf.format(new Date());

        // 拼接当天投票的key
        String voteKey = "vote:" + date;

        // 将IP添加到Set中,记录当天所有投票的IP
        redisTemplate.opsForSet().add(voteKey,ip);

        // 获取当天已经投票的IP数量
        long voteCount = redisTemplate.opsForSet().size(voteKey);

        // 判断是否超过投票限制
        if(voteCount > 10){
            return "您今天的投票数已经用尽!";
        }

        // 记录已经投票,设置过期时间为1天
        redisTemplate.opsForValue().set(key,"已经投票", 1, TimeUnit.DAYS);

        return "投票成功!";
    }
}

五、 实现同一IP每天刷票不得超过次数

1. 在VoteController的submit接口中实现同一IP每天刷票不得超过次数

每次投票时,先通过Redis查看是否已经投过票,如果已经投过票,则返回“您已经投过票了!”,否则将该IP添加到当天投票的Set中,再通过Redis查看当天投票的IP数量是否超过设定的阈值,如果超过则返回“您今天的投票数已经用尽!”,否则记录已经投票,并将该条记录设置为1天后过期。

上述逻辑可以采用Redis提供的Set和过期时间来完成,便捷高效。

2. 优化方案

上述实现在高并发情况下可能存在问题,比如多个用户同时投票,从而同时访问Redis,产生并发问题或者性能问题,为此可以通过Redis的分布式锁或者使用Redisson等第三方库来解决。

下面简单介绍一下使用Redisson来实现分布式锁。

  • a. 在pom.xml中加入Redisson依赖
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.12.6</version>
</dependency>
  • b. 在application.yml中加入Redisson配置
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0

redisson:
    address: redis://127.0.0.1:6379
  • c. 新建RedissonConfig.java
@Configuration
public class RedissonConfig {
    @Autowired
    private Environment env;

    @Bean(destroyMethod = "shutdown")
    RedissonClient redisson() throws IOException {
        // use "redis://" as the protocol
        Config config = new Config();
        config.useSingleServer().setAddress(env.gandroidetProperty("redisson.address"));
        return Redisson.create(config);
    }
}
  • d. 在VoteController中加入Redisson分布式锁
@RestController
@RequestMapping("/vote")
public class VoteController {

    private final StringRedisTemplate redisTemplate;
    private final RedissonClient redissonClient;

    public VoteController(StringRedisTemplate redisTemplate, RedissonClient redissonClient) {
        this.redisTemplate = redisTemplate;
        this.redissonClient = redissonClient;
    }

    /**
     * 投票接口
     * @param ip
     * @return
     */
    @PostMapping("/submit")
    public String submit(@RequestParam String ip){

        String key = "ip:" + ip;

        // 使用Redisson加锁
        RLwww.chinasem.cnock lock = redissonClient.getLock(key);
        lock.lock();

        try {
           OXUNGki // 先判断是否已经投票,如果已经投票,则返回
            if (redisTemplate.opsForValue().get(key) != null) {
                return "您已经投过票了!";
            }

            // 获取当天的日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String date = sdf.format(new Date());

            // 拼接当天投票的key
            String voteKey = "vote:" + date;

            // 将IP添加到Set中,记录当天所有投票的IP
            redisTemplate.opsForSet().add(voteKey, ip);

            // 获取当天已经投票的IP数量
            long voteCount = redisTemplate.opsForSet().size(voteKey);

            // 判断是否超过投票限制
            if (voteCount > 10) {
                return "您今天的投票数已经用尽!";
            }

            // 记录已经投票,设置过期时间为1天
            redisTemplate.opsForValue().set(key, "已经投票", 1, TimeUnit.DAYS);

            return "投票成功!";
        } finally {
            lock.unlock();
        }
    }
}

以上是使用Redisson实现分布式锁的思路及代码,从而在高并发情况下,避免了多个用户同时对Redis进行访问的并发问题。

六、总结

本文介绍了如何使用SpringBoot和Redis实现刷票过滤,自定义同一IP每天刷票不得超过次数的功能。

通过使用Redis的Set和过期时间,实现了同一IP每天刷票不得超过次数的限制,并且代码简单高效。

在高并发情况下,通过使用Redisson等库实现分布式锁,避免了多个用户同时访问Redis的性能问题。

在实际应用中,除了IP限制和过期时间设置外,还可以根据具体需求,对投票做更细粒度的控制,比如设置对投票用户的身份验证、对投票的时间和场次进行限制等等。

最后,需要注意的是,防范恶意刷票是非常重要的,但是过度的限制可能也会造成用户体验不佳,需要在保障数据安全的前提下,兼顾用户体验的优化。

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

参考资料:

  1. Spring Boot官方文档
  2. Redis官方文档
  3. Redisson官方文档

这篇关于Redis如何实现刷票过滤的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153859

相关文章

Python实现常用文本内容提取

《Python实现常用文本内容提取》在日常工作和学习中,我们经常需要从PDF、Word文档中提取文本,本文将介绍如何使用Python编写一个文本内容提取工具,有需要的小伙伴可以参考下... 目录一、引言二、文本内容提取的原理三、文本内容提取的设计四、文本内容提取的实现五、完整代码示例一、引言在日常工作和学

Python实战之屏幕录制功能的实现

《Python实战之屏幕录制功能的实现》屏幕录制,即屏幕捕获,是指将计算机屏幕上的活动记录下来,生成视频文件,本文主要为大家介绍了如何使用Python实现这一功能,希望对大家有所帮助... 目录屏幕录制原理图像捕获音频捕获编码压缩输出保存完整的屏幕录制工具高级功能实时预览增加水印多平台支持屏幕录制原理屏幕

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

SpringBoot3使用Jasypt实现加密配置文件

《SpringBoot3使用Jasypt实现加密配置文件》这篇文章主要为大家详细介绍了SpringBoot3如何使用Jasypt实现加密配置文件功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编... 目录一. 使用步骤1. 添加依赖2.配置加密密码3. 加密敏感信息4. 将加密信息存储到配置文件中5

Python实现自动化表单填写功能

《Python实现自动化表单填写功能》在Python中,自动化表单填写可以通过多种库和工具实现,本文将详细介绍常用的自动化表单处理工具,并对它们进行横向比较,可根据需求选择合适的工具,感兴趣的小伙伴跟... 目录1. Selenium简介适用场景示例代码优点缺点2. Playwright简介适用场景示例代码

SpringBoot整合jasypt实现重要数据加密

《SpringBoot整合jasypt实现重要数据加密》Jasypt是一个专注于简化Java加密操作的开源工具,:本文主要介绍详细介绍了如何使用jasypt实现重要数据加密,感兴趣的小伙伴可... 目录jasypt简介 jasypt的优点SpringBoot使用jasypt创建mapper接口配置文件加密

SpringBoot项目使用MDC给日志增加唯一标识的实现步骤

《SpringBoot项目使用MDC给日志增加唯一标识的实现步骤》本文介绍了如何在SpringBoot项目中使用MDC(MappedDiagnosticContext)为日志增加唯一标识,以便于日... 目录【Java】SpringBoot项目使用MDC给日志增加唯一标识,方便日志追踪1.日志效果2.实现步

Spring Boot 集成 Quartz 使用Cron 表达式实现定时任务

《SpringBoot集成Quartz使用Cron表达式实现定时任务》本文介绍了如何在SpringBoot项目中集成Quartz并使用Cron表达式进行任务调度,通过添加Quartz依赖、创... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启

Redis中的常用的五种数据类型详解

《Redis中的常用的五种数据类型详解》:本文主要介绍Redis中的常用的五种数据类型详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis常用的五种数据类型一、字符串(String)简介常用命令应用场景二、哈希(Hash)简介常用命令应用场景三、列表(L

Python实现html转png的完美方案介绍

《Python实现html转png的完美方案介绍》这篇文章主要为大家详细介绍了如何使用Python实现html转png功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 1.增强稳定性与错误处理建议使用三层异常捕获结构:try: with sync_playwright(