应选 ConcurrentHashMap 而非 HashMap 或 ArrayList;ConcurrentHashMap 保证并发安全,配合 CopyOnWriteArrayList 存明细;防重投需数据库唯一约束或 Redis SETNX;接口须 POST+token+限流;结果刷新优先轮询而非 WebSocket。
投票数据结构怎么选:用 Map 还是 List?
核心问题不是“能存”,而是“查得快、改得稳、并发不崩”。
最常用,键是选项名(如
),值是票数;但多线程环境下直接用会出错——
是更稳妥的选择。别用
存原始投票记录再遍历统计,那是 O(n) 查询,10 万条数据就明
显卡
顿。
如果需要保留用户 ID 和投票时间,得建实体类:
此时用
统计,再配一个
存明细(写少读多场景下合适)。
如何防止重复投票:校验逻辑放哪?
不能只靠
前端
限制,后端必须做唯一性校验。常见错误是把
存在
session
或内存 map 里,服务重启就失效。正确做法是持久化记录,哪怕只是用本地文件或 H2 内存数据库:
用
存已投票
—— 仅限单机、临时测试,重启即丢
真实项目必须查数据库表(如
),插入前用
(PostgreSQL)或
(MySQL)避免异常
若用 Redis,用
命令 + 过期时间(如
),比单纯存 key 更安全
投票接口怎么设计才不容易被刷:简单但有效的防护
没加防护的
接口,用
curl
循环调 1000 次就乱套。基础防护三件事必须做:
接口必须是
,参数走 body(如 JSON:
),拒绝 GET 参数式投票
每个用户首次投票发一个短期有效 token(如 JWT,有效期 5 分钟),验证
签名和过期时间,且服务端记录该 token 是否已被使用
加简单限流:用
限制单个
每分钟最多投 1 票,
统计结果实时刷新怎么做:别一上来就上 WebSocket
小规模投票(百人内)根本不需要 WebSocket。先用最省事的方案:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
前端每 5 秒发一次
,返回 JSON:
后端用
+
直接返回,无锁读取,毫秒级响应
真要“实时”且并发高,再考虑用 Spring WebFlux +
推送,或者用 Redis Pub/Sub 让投票成功时
,多个实例都能监听
很多人一想到“实时”就堆技术,其实多数内部投票系统,轮询 + 缓存响应头(
)已经够用。真正难的是数据一致性和防刷,不是刷新快慢。
HashMap"A"ConcurrentHashMapArrayListpublic class Vote {
private String userId;
private String option;
private long timestamp;
}ConcurrentHashMapCopyOnWriteArrayListuserIdHashSetuserIdvoted_users(userId VARCHAR PRIMARY KEY)INSERT ... ON CONFLICT DO NOTHINGINSERT IGNORESETNXSETNX voted:123 true EX 86400/vote?option=A&user=abcPOST{"option":"A","token":"xyz"}tokenGuava RateLimiteruserIdRateLimiter limiter = RateLimiter.create(1.0); // 1 per minute
if (!limiter.tryAcquire()) { throw new IllegalStateException("Too many requests"); }GET /api/results{"A": 42, "B": 31, "C": 19}@RestControllerConcurrentHashMapFlux.interval()PUBLISH results-update ""Cache-Control: no-cache