51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个360安全卫士的“安全漏洞扫描”服务,该服务在高峰时段(如每日凌晨)处理大量用户请求,请描述系统架构、限流策略、缓存策略和数据库优化方案。

360服务端开发工程师-Golang难度:中等

答案

1) 【一句话结论】
针对360安全卫士漏洞扫描服务,采用微服务架构,通过动态限流(基于QPS/CPU的令牌桶参数自调)、分层缓存(热点数据+结果缓存+随机过期防雪崩)、分库分表+读写分离的数据库优化,确保高峰时段高并发下的服务稳定性与性能。

2) 【原理/概念讲解】
系统架构分为四层:前端网关(请求路由与限流)、任务调度中心(生成任务并放入消息队列)、任务执行集群(多实例消费任务执行扫描)、结果存储层(Redis缓存+MySQL持久化)。

  • 限流策略:采用令牌桶算法(按时间生成固定数量令牌,请求消耗令牌,类比“交通收费站”,允许短时间突发但总量有限);通过Prometheus采集QPS、CPU等指标,当QPS超过阈值(如1000)或CPU > 80%时,动态降低令牌桶填充速率(从10个/秒降至5个/秒),调整桶大小以适应流量波动。
  • 缓存策略:将高频访问的漏洞特征库(热点数据)缓存至Redis,减少数据库查询;扫描结果也缓存,快速响应历史请求;设置随机过期时间(如T=3600秒,Δ=300秒,过期时间在3300-3900秒内随机),预防缓存雪崩;对缓存热点数据采用分布式锁(如Redis锁)防击穿。
  • 数据库优化:采用读写分离(主库写,从库读,分散读压力);按用户ID哈希分库(如用户ID % 8取模分配至不同库),避免单库数据过大;按任务时间/任务ID分表(如按任务创建时间分表),处理热点表(近期数据多时,时间分表结合负载均衡,避免单表查询慢);对扫描结果的关键字段(用户ID、任务ID、任务时间)建索引,加速查询。

3) 【对比与适用场景】

策略/组件定义特性使用场景注意点
限流算法(令牌桶)维持固定大小桶,按时间生成令牌,请求消耗令牌流量平滑,允许突发但总量有限,支持动态调整高峰时段流量控制(漏洞扫描服务)需合理设置桶大小与填充速率,动态调整需结合监控指标
限流算法(漏桶)维持固定大小漏斗,按固定速率流出令牌,请求消耗令牌严格限制突发流量,流量恒定系统资源严格限制场景可能导致请求积压,不适合突发流量
缓存(热点数据:漏洞库)高频访问数据存入Redis高速读取,减少数据库压力漏洞特征库(用户频繁扫描的常见漏洞)需设置随机过期时间防雪崩,避免数据过时
缓存(结果数据)用户扫描结果存入Redis快速返回历史结果,减少重复计算用户常用扫描结果(系统已扫描过的漏洞)需互斥锁防击穿,确保缓存一致性
数据库分库分表(哈希分库)按用户ID哈希分配至不同数据库避免单库数据膨胀,提升写性能高并发写场景(用户任务量大的漏洞扫描)分库规则需均匀分布,避免热点库
数据库分库分表(时间分表)按任务时间或任务ID分表提升查询效率,避免单表数据过大热点表(近期数据多时)分表键需合理选择,如按时间范围分表,结合负载均衡
数据库读写分离主库写,从库读分散读压力,提升读性能高并发读场景(结果查询)需保证从库数据一致性(如延迟不超过秒级)

4) 【示例】
伪代码(用户提交扫描请求与任务执行流程):

// 用户提交扫描请求
func submitScanRequest(ctx context.Context, userId string, deviceInfo string) error {
    // 1. 限流检查(前端网关)
    if !isAllowed(ctx, userId) {
        return errors.New("request too frequent")
    }
    // 2. 生成任务ID
    taskId := generateTaskId()
    // 3. 放入消息队列(Kafka,持久化存储)
    err := kafkaProducer.Send(ctx, "scan_tasks", map[string]interface{}{
        "user_id": userId,
        "task_id": taskId,
        "device_info": deviceInfo,
    })
    return err
}

// 任务执行服务消费消息(动态限流调整示例)
func processScanTask(ctx context.Context, task map[string]interface{}) {
    userId := task["user_id"].(string)
    taskId := task["task_id"].(string)
    deviceInfo := task["device_info"].(string)

    // 1. 从Redis缓存漏洞库(热点数据)
    vulnerabilities, err := getVulnerabilitiesFromCache()
    if err != nil {
        // 数据库 fallback
        vulnerabilities, err = getVulnerabilitiesFromDB()
        if err != nil {
            return
        }
        // 雪崩预防:缓存后设置随机过期
        setVulnerabilitiesToCache(vulnerabilities, randomExpireTime(3600, 300)) // 随机过期时间
    }

    // 2. 扫描设备
    scanResult := scanDevice(deviceInfo, vulnerabilities)

    // 3. 存储结果(互斥锁防击穿)
    lock := getMutexLock(userId, taskId)
    defer releaseMutex(lock)
    setScanResultToCache(userId, taskId, scanResult)
    saveScanResultToDB(userId, taskId, scanResult) // 持久化
}

// 动态限流调整函数(假设由监控服务触发)
func adjustRateLimiter(rateLimiter *TokenBucket, qps, cpuUsage float64) {
    // 阈值规则:QPS > 1000 或 CPU > 80% 时调整
    if qps > 1000 || cpuUsage > 80 {
        rateLimiter.setRate(5) // 降低填充速率
    } else {
        rateLimiter.setRate(10) // 恢复正常速率
    }
}

5) 【面试口播版答案】
面试官您好,针对360安全卫士的漏洞扫描服务,我会从系统架构、限流、缓存、数据库优化四个方面设计。首先,系统采用微服务架构,分为前端网关、任务调度中心、任务执行集群、结果存储层四层。前端网关负责请求限流,任务调度中心将请求转化为消息队列任务,任务执行集群消费并处理,结果存入Redis和MySQL。限流策略用令牌桶算法,控制高峰时段的请求速率,并通过Prometheus监控QPS和CPU,当QPS超过1000时,动态降低令牌桶填充速率(从10个/秒降至5个/秒),调整桶大小以适应流量波动。缓存方面,将漏洞特征库(热点数据)缓存到Redis,减少数据库查询;扫描结果也缓存,快速响应历史请求,同时设置随机过期时间(如3600秒±300秒随机),预防缓存雪崩;对缓存热点数据采用分布式锁防击穿。数据库优化采用读写分离,主库写,从库读;按用户ID哈希分库(如用户ID % 8取模),按任务时间分表,避免单表数据过大;对扫描结果的关键字段(用户ID、任务ID、时间)建索引,提升查询效率。这样设计能确保高峰时段高并发下的服务稳定性和性能。

6) 【追问清单】

  • 问:如何验证限流参数动态调整的有效性?
    答:通过监控服务记录调整前后的QPS、CPU变化,对比响应延迟和错误率,确保调整后服务仍稳定。
  • 问:缓存雪崩的随机过期时间具体如何实现?
    答:使用Redis的EXPIRE命令,在设置缓存时计算随机过期时间(如T=3600秒,Δ=300秒,则过期时间在3300-3900秒内随机),避免集中过期。
  • 问:数据库分库分表的热点表(如近期任务表)如何处理?
    答:采用时间分表(按任务创建时间范围分表),结合负载均衡策略,将查询请求分散到不同分表,避免单表查询压力过大。
  • 问:限流参数动态调整的阈值规则是否考虑了业务波动?
    答:结合业务高峰时段(如凌晨)的流量特征,设置动态阈值(如QPS阈值根据历史数据调整),避免静态阈值导致服务崩溃。
  • 问:任务队列如何保证消息不丢失?
    答:使用消息队列的持久化存储(如Kafka的日志持久化),并设置重试机制(如失败后重试3次,超时后标记为失败),确保任务最终被处理。

7) 【常见坑/雷区】

  • 坑1:限流参数静态设置,未结合实时流量监控,导致高峰时段流量超过阈值引发服务崩溃。
  • 坑2:缓存未设置随机过期时间,导致缓存雪崩时大量请求落库,数据库压力激增。
  • 坑3:数据库未做分库分表,单表数据过大导致查询慢,高峰时段读延迟高。
  • 坑4:分库分表规则不合理(如按时间分表但未考虑热点),导致近期数据集中在一个分表,查询性能下降。
  • 坑5:限流只限接口,未考虑任务队列,导致任务队列积压,用户请求响应延迟。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1