• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    Redis如何实现刷票过滤

    发布者: 涵韵3588 | 发布时间: 2025-6-19 12:40| 查看数: 85| 评论数: 0|帖子模式

    引言

    随着互联网的不断发展,网站或APP的用户流量增加,也衍生出了一些恶意刷量等问题,给数据分析及运营带来极大的困难,出现的刷票问题更是造成了严重的经济损失,所以网站或APP对恶意刷票进行过滤是十分必要的。
    Redis提供了很好的解决方案,其提供的内存存储和Key-Value的存储结构,能够高效地实现刷票过滤。
    本文主要介绍如何使用SpringBoot和Redis实现刷票过滤,自定义同一IP每天刷票不得超过次数。

    一、概述

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

    • 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依赖
    1. <dependency>
    2.         <groupId>org.springframework.boot</groupId>
    3.         <artifactId>spring-boot-starter-data-redis</artifactId>
    4. </dependency>
    复制代码
    2.在application.yml中配置Redis:
    1. spring:
    2.   redis:
    3.     host: 127.0.0.1
    4.     port: 6379
    复制代码
    3. 在RedisConfig.java中配置RedisTemplate和StringRedisTemplate
    1. @Configuration
    2. public class RedisConfig {
    3.     @Bean
    4.     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
    5.         RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    6.         redisTemplate.setConnectionFactory(redisConnectionFactory);
    7.         redisTemplate.setKeySerializer(new StringRedisSerializer());
    8.         redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
    9.         redisTemplate.afterPropertiesSet();
    10.         return redisTemplate;
    11.     }

    12.     @Bean
    13.     public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory){
    14.         StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
    15.         stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
    16.         return stringRedisTemplate;
    17.     }
    18. }
    复制代码
    四、使用SpringBoot开发应用

    1.在pom.xml中加入SpringBoot依赖
    1. <dependency>
    2.     <groupId>org.springframework.boot</groupId>
    3.     <artifactId>spring-boot-starter-web</artifactId>
    4. </dependency>
    复制代码
    2.新建Controller
    1. @RestController
    2. @RequestMapping("/vote")
    3. public class VoteController {

    4.     private final StringRedisTemplate redisTemplate;

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

    8.     /**
    9.      * 投票接口
    10.      * @param ip
    11.      * @return
    12.      */
    13.     @PostMapping("/submit")
    14.     public String submit(@RequestParam String ip){

    15.         String key = "ip:" + ip;

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

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

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

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

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

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

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

    35.         return "投票成功!";
    36.     }
    37. }
    复制代码
    五、 实现同一IP每天刷票不得超过次数

    1. 在VoteController的submit接口中实现同一IP每天刷票不得超过次数
    每次投票时,先通过Redis查看是否已经投过票,如果已经投过票,则返回“您已经投过票了!”,否则将该IP添加到当天投票的Set中,再通过Redis查看当天投票的IP数量是否超过设定的阈值,如果超过则返回“您今天的投票数已经用尽!”,否则记录已经投票,并将该条记录设置为1天后过期。
    上述逻辑可以采用Redis提供的Set和过期时间来完成,便捷高效。
    2. 优化方案
    上述实现在高并发情况下可能存在问题,比如多个用户同时投票,从而同时访问Redis,产生并发问题或者性能问题,为此可以通过Redis的分布式锁或者使用Redisson等第三方库来解决。
    下面简单介绍一下使用Redisson来实现分布式锁。

    • a. 在pom.xml中加入Redisson依赖
    1. <dependency>
    2.     <groupId>org.redisson</groupId>
    3.     <artifactId>redisson</artifactId>
    4.     <version>3.12.6</version>
    5. </dependency>
    复制代码

    • b. 在application.yml中加入Redisson配置
    1. spring:
    2.   redis:
    3.     host: 127.0.0.1
    4.     port: 6379    database: 0redisson:    address: redis://127.0.0.1:6379
    复制代码

    • c. 新建RedissonConfig.java
    1. @Configuration
    2. public class RedissonConfig {
    3.     @Autowired
    4.     private Environment env;

    5.     @Bean(destroyMethod = "shutdown")
    6.     RedissonClient redisson() throws IOException {
    7.         // use "redis://" as the protocol
    8.         Config config = new Config();
    9.         config.useSingleServer().setAddress(env.getProperty("redisson.address"));
    10.         return Redisson.create(config);
    11.     }
    12. }
    复制代码

    • d. 在VoteController中加入Redisson分布式锁
    1. @RestController
    2. @RequestMapping("/vote")
    3. public class VoteController {

    4.     private final StringRedisTemplate redisTemplate;
    5.     private final RedissonClient redissonClient;

    6.     public VoteController(StringRedisTemplate redisTemplate, RedissonClient redissonClient) {
    7.         this.redisTemplate = redisTemplate;
    8.         this.redissonClient = redissonClient;
    9.     }

    10.     /**
    11.      * 投票接口
    12.      * @param ip
    13.      * @return
    14.      */
    15.     @PostMapping("/submit")
    16.     public String submit(@RequestParam String ip){

    17.         String key = "ip:" + ip;

    18.         // 使用Redisson加锁
    19.         RLock lock = redissonClient.getLock(key);
    20.         lock.lock();

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

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

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

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

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

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

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

    41.             return "投票成功!";
    42.         } finally {
    43.             lock.unlock();
    44.         }
    45.     }
    46. }
    复制代码
    以上是使用Redisson实现分布式锁的思路及代码,从而在高并发情况下,避免了多个用户同时对Redis进行访问的并发问题。

    六、总结

    本文介绍了如何使用SpringBoot和Redis实现刷票过滤,自定义同一IP每天刷票不得超过次数的功能。
    通过使用Redis的Set和过期时间,实现了同一IP每天刷票不得超过次数的限制,并且代码简单高效。
    在高并发情况下,通过使用Redisson等库实现分布式锁,避免了多个用户同时访问Redis的性能问题。
    在实际应用中,除了IP限制和过期时间设置外,还可以根据具体需求,对投票做更细粒度的控制,比如设置对投票用户的身份验证、对投票的时间和场次进行限制等等。
    最后,需要注意的是,防范恶意刷票是非常重要的,但是过度的限制可能也会造成用户体验不佳,需要在保障数据安全的前提下,兼顾用户体验的优化。
    这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
    参考资料:

    来源:https://www.jb51.net/database/338108fyc.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表