签到系统如何设计?
- 场景1:公司签到系统,假设是万人级别公司的签到系统。
- 特点:并发量小,签到均匀分布在上午上下班时段。
- 设计:使用mysql表存储。
- mysql表字段:id、用户id、日期、是否签到(或签到时间)。
- 存储逻辑:每个用户每天签到都会增加一条数据。
- 场景2:线上活动签到,假设瞬时并发量到千万级别。
- 特点:瞬时并发量大。
- 设计:同时使用redis和mysql,redis用来应对瞬时大量并发访问,避免数据库崩溃。
- redis存储结构:bitmap或hash,hash可以存储准确的签到时刻,而bitmap只能存储某天是否签到。
- redis存储逻辑:使用<用户id:日期>作为key值,存储近两天的数据,设置过期时间为两天(即后天过期)。
- mysql表字段:id、用户id、日期、是否签到(或签到时间)。
- 代码逻辑:使用定时任务在流量低谷期(半夜2-4点)对redis中昨天的签到数据进行统计并同步到mysql中。
- 场景3:大数据量的签到数据需要存储,但是瞬时并发量并不大,需要尽量节省存储空间。
- 特定:数据量大。
- 设计1:使用位图的思想存储到mysql中。
- mysql表字段:id、用户id、年份、位图(366位)。
- 存储逻辑:将用户年签到数据按序存储到位图中,1表示已签到,0表示未签到。
- 设计2:一条记录表示连续签到的次数和最晚的签到时间。
- mysql表字段:id、用户id、连续签到天数,最晚签到时间。
- 存储逻辑:一条记录表示用户连续签到的信息,从而减少记录数量。例如按场景1表的设计方案连续签到10天需要存储10条数据,基于这种表设计则只需要存储一条数据。
CPU一直满载,如何排查问题?
第三方登录系统如何设计?
每天上百个机构都有十万级别数据量的新增和删除
项目中如何进行分库分表的
项目中是如何优化数据库查询的
数据导出造成的OOM异常
问题:将大百万数据单线程直接导入到Excel发生了OOM异常,内存4G,使用的工具是EasyPOI。
解决思路:多线程分页分批导出
将百万数据进行分页,每一页25万条数据,使用线程池查询每页的数据执行导出任务,将文件导出到本地文件夹中,通过countDownLatch等待所有线程导出完成后,计算总耗时时间。
性能提升:从可能出现OOM异常和长耗时1分钟,到最后耗时降低到9秒左右。
问题解析:老年代大对象内存溢出问题
通过VisualVM工具查看JVM内存占用情况:发现老年内存占用爆炸时增加,立马出现了OOM异常。
主要原因:JDBC查询百万数据时将数据放入一个字节数组中,然后通过结果集resultSet传输到应用层,应用层通过List接受数据,这里字节数组存储的大对象达到了老年代内存上线,所以出现了OOM异常。所以我们通过将循环将数据进行分页查询,这样就能将大对象分解成若干个较小的对象的方式进行串行查询,因为JDBC每次查询字节数组并封装resultSet后都会释放字节数组元素,所以也就并不会达到老年代内存上线。解决问题的关键是单次查询时生成的字节数组大对象是否超过了老年带的内存上线。
发表回复