专业的JAVA编程教程与资源

网站首页 > java教程 正文

深夜报警!10亿次请求暴击,如何用Redis找出最热IP?

temp10 2025-04-30 19:31:06 java教程 6 ℃ 0 评论

凌晨3点26分,你的手机突然炸了——
10亿次请求正在冲击服务器,CPU飙到100%!
更可怕的是:
老板问你:"到底是哪个IP在攻击我们?"

如果支支吾吾答不上来,明天就可以收拾工位了…

深夜报警!10亿次请求暴击,如何用Redis找出最热IP?

别慌!今天我们用Redis+Java代码,彻底解决这个亿级数据下的"最热IP统计"难题!

▎01 方案对比:Redis五种统计方案谁最强?

(实测数据来自4核8G云服务器,10亿UV统计场景)

真实案例:某社交APP用Hash方案统计UV,服务器每天凌晨准时崩溃,改用HLL后成本直降99%


▎02 终极方案:RedisBloom TopK(压测代码)

Redis的Bloom模块提供了精确的TopK统计,原理如下:

Java实现代码(SpringBoot版):

@RestController
public class TopIPController {


    @Resource
    private RedisTemplate<String, String> redisTemplate;


    // 统计IP访问
    @PostMapping("/visit")
    public void recordVisit(@RequestParam String ip) {
        redisTemplate.opsForValue()
            .setBit("ip_bitmap:" + ip, 1, true);  // 用Bitmap去重


        redisTemplate.opsForZSet()
            .incrementScore("ip_rank", ip, 1);    // ZSet计数
    }


    // 获取Top10 IP
    @GetMapping("/top10")
    public List<String> getTop10IP() {
        return redisTemplate.opsForZSet()
            .reverseRange("ip_rank", 0, 9);
    }


    // 使用BloomFilter版TopK(需Redis 5.0+)
    public void initTopK() {
        redisTemplate.execute((RedisCallback<Object>) connection -> {
            connection.execute("TOPK.RESERVE", "ip_topk".getBytes(), 
                "10".getBytes(), // 保留Top10
                "10000".getBytes(), // 计数器数量
                "0.01".getBytes()); // 误差率1%
            return null;
        });
    }
}

性能实测(10亿IP场景):

▎03 分片优化:百亿级数据的处理技巧

如果数据量超过单机Redis容量,就要用分片方案:

Java分片代码示例:

// 根据IP的CRC16分片
public int getShard(String ip) {
    int slot = CRC16.crc16(ip.getBytes()) % 16384;
    return slot / 5461;  // 假设分3片
}


// 分片统计
public void shardedRecord(String ip) {
    int shard = getShard(ip);
    redisTemplates.get(shard).opsForZSet()
        .incrementScore("ip_rank", ip, 1);
}

分片后性能提升:

  • 内存压力分散到多台机器
  • 查询吞吐量提升N倍(N=分片数)

▎04 防作弊:如何识别刷量IP?

识别异常IP的4个维度(附代码):

  • 频率检测:1秒内请求超过100次
String key = "ip_limit:" + ip;
Long count = redisTemplate.opsForValue().increment(key);
redisTemplate.expire(key, 1, TimeUnit.SECONDS);
if(count > 100) throw new RuntimeException("刷量IP!");

  • 设备指纹:相同UserAgent+IP组合
  • 行为分析:只访问特定API的IP
  • 地理位置:突发的境外IP请求

▎05 彩蛋:Redis模块安装指南

TopK功能需要RedisBloom模块,安装步骤:

# 1. 下载模块
wget https://github.com/RedisBloom/RedisBloom/archive/refs/tags/v2.4.5.tar.gz


# 2. 编译
make && cp redisbloom.so /path/to/modules/


# 3. 启动Redis时加载
redis-server --loadmodule /path/to/redisbloom.so

实战总结:

  1. 10万级以下
  2. 直接用ZSet
  3. 百万~十亿级
  4. TopK+分片
  5. 百亿级以上
  6. Flink+Redis分层存储

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表