6-1 HashMap和CurrentHashMap的区别是什么? CurrentHashMap底层结构在1.7和1.8有什么不同?
- hashmap:这是一个非线程安全的Map实现。如果在多线程环境中使用它,可能会遇到数据不一致的问题。
- ConcurrentHashMap:这是一个线程安全的Map实现。它提供了对整个Map的外部同步,以及内部的无锁机制,使得它在多线程环境中表现得更好。
至于ConcurrentHashMap在Java 1.7和1.8中的底层结构变化,主要的区别在于内部锁的实现和哈希算法的改进。
在Java 1.7中,ConcurrentHashMap使用分段锁(Segmentation)技术来实现并发控制。它将整个Map分成多个段(Segment),每个段都是一个小的ConcurrentHashMap。当一个线程访问一个键值对时,它首先通过计算键的哈希值找到对应的段,然后在该段上进行操作。这样可以显著降低锁的粒度,从而提高并发性能。
在Java 1.8中,ConcurrentHashMap对内部结构进行了优化,移除了Segment的概念,改为使用一种称为“红黑树+链表”的结构来处理哈希冲突。当链表长度超过一定阈值时,链表会转换为红黑树,以提高查找效率。此外,还引入了动态调整数组大小的功能,以更好地适应数据变化。
6-2 假设你有一批历史积分数据要存储,数量在kw条左右 存入mysql 你的方案是什么
首先对于海量数据的存储我们常见的方案又:分区,分表,集群,分库
1.表分区:他是一种数据存储方案,可以解决单表数据较多的问题,在masql5.1之后开始支持表分区功能,优点:
• 可以存储更多的数据,突破单表上限,甚至可以存储到不同磁盘,突破磁盘上限
• 查询时可以根据规则只检索某一个文件,提高查询效率
• 数据统计时,可以多文件并行统计,最后汇总结果,提高统计效率
• 对于一些历史数据,如果不需要时,可以直接删除分区文件,提高删除效率
2.分表:分表是一种表设计方案,由开发者在创建表时按照自己的业务需求拆分表。优点是:
• 拆分方式更加灵活
• 可以解决单表字段过多和数据过多的问题
因为是历史积分和海量的数据我选择分表因为1.他拆分方式更加灵活2.可以解决单表字段过多和数据过多的问题
6-3 请你说一说你的排行榜功能是如何实现的
我们的排行榜是主要根据积分实现的,我们分为实时积分榜和历史积分榜,具体实现步骤:
1.实时积分榜由于查询量非常大,我们把它存在了redis里面,使用了redis里的zset结构,我们用榜单日期做key,vealue取得是哦用户的id,分数是取得积分的总量然后跟据分数去排序
2.历史积分榜由于数据量比较大,但是查询量没有那么高,所以我们把它存在了mysql里面,在mysql中我们为了防止单表的数据量过多,采用了分表的设计方案,我们把一个赛季的数据放在一张表里,这样在查询的时候只需要根据标识查询一张表即可。
3.最后我们的排行榜功能就是这样实现的。
6-4 历史赛季积分是如何生成的
历史赛季积分生成是将上个赛季的记录数据由redis保存到mysql中去,具体实现步骤
1.首先要生一个空的历史记录数据表,用来存储历史数据]
2.将redis中的数据转到mysql中保存起来
3.最后清理掉redis中的缓存记录
4.因为这个操作不是认为操作的需要每隔一段特定的时间去执行所以我们使用xxl-job设置了定时任务并且采用子任务方式是他们按顺序进行
以上就是生成历史积分记录的大体步骤.