6-1 HashMap和ConcurrentHashMap的区别是什么? ConcurrentHashMap底层结构在1.7和1.8有什么不同?
HashMap和CurrentHashMap都是Map集合的子类,都可以存储键值对的数据,都是基于哈希表实现的,区别在于:
1、线程安全:HashMap是非线程安全的,ConcurrentHashMap是线程安全的;
2、性能:在单线程下,HashMap的性能比ConcurrentHashMap稍好;在多线程并发访问时, ConcurrentHashMap有更好的性能;
3、并发度:HashMap不支持并发操作,而ConcurrentHashMap支持高度的并发度;
4、迭代器:HashMap的迭代器不是线程安全的,在迭代过程中其他线程修改了HashMap,可能会导致ConcurrentModificationException异常;ConcurrentHashMap的迭代器是弱一致性的,允许在迭代过程中进行修改;
ConcurrentHashMap底层结构在1.7和1.8的区别:
在Java1.7中,ConcurrentHashMap底层采用了分段数组+链表实现;使用了分段锁来实现线程安全性,每个段Segment有自己的锁。
在Java1.8中,ConcurrentHashMap进行了重大改进,引入了一种新的数据结构,结合了CAS操作和链表/红黑树。它不再使用分段锁,而是采用更细粒度的锁策略。
总之,Java1.8中的ConcurrentHashMap在性能和并发性方面有一些改进,这些改进使得Java1.8中的ConcurrentHashMap在高并发环境中表现更优秀。
6-2 假设你有一批历史积分数据要存储,数量在kw条左右 存入mysql 你的方案是什么
存储千万条的历史积分数据到mysq,需要考虑数据库设计、性能优化和数据导入等方面;对于数据库的海量数据存储,方案有很多,常见的有分区、分表、分库、集群;
在我的项目中我采用的是分表,以每个赛季为基准进行分表,水平分出不同的表,每张表中存入对应赛季的数据;在查询时按照赛季查对应的表即可。
这是我对于海量数据存储到mysql的方案。
6-3 请你说一说你的排行榜功能是如何实现的
我们排行榜主要是根据积分进行排行的,主要有实时积分榜和历史积分榜;
实时积分榜由于查询量非常大,存储到了redis的zset结构,用月份做键,用户id作为值,积分作为分数实现自动排序;
历史积分数据量虽然大,但查询量相对较低,所以存储到了mysql;
在mysql为了防止单表数据量过多,我们采用了分表的设计方案,把一个赛季的数据放到一张表里,我们在查询时根据赛季标识查询,只用查一张表即可。
以上就是我项目中积分功能的实现。
6-4 历史赛季积分是如何生成的
历史赛季积分的生成主要分为三大步,核心把redis上一个赛季的数据保存到mysql中;
第一步是根据每个赛季创建一张数据表;
第二步redis数据转存到mysql里面;
第三步删除redis缓存数据;
由于赛季积分生产是在每月一号凌晨执行的,我采用了xxl-job定时任务;
最后通过设置子任务来保证任务链的执行顺序。