6-1 HashMap和CurrentHashMap的区别是什么? ?CurrentHashMap底层结构在1.7和1.8有什么不同?
? ? ? ?HashMap和CurrentHashMap都是map接口的实现类,继承类map的基本特性,HashMap效率高但是线程不安全,CurrentHashMap效率比HashMap低,但是线程安全。因此在企业开发中我们通常在追求效率而不追求安全的情况下使用HashMap。在需要线程安全的情况下,也追求一点效率使用CurrentHashMap。CurrentHashMap和HashMap底层原理基本一样只不过在一些操作使用了cas,有些地方加了锁。
CurrentHashMap底层结构在1.7和1.8有什么不同
1.7CurrentHashMap的链表是头插法,1.8之后是尾插法,
? ? ? ?原因主要是因为1.7用头插法考虑到了一个热点数据的点,也就是新插入的数据可能早用到,但是这在CurrentHashMap底层数组扩容的时候也就是rehash的时候,旧链表迁移新链表的时候呢,如果新表的数组索引位置相同,则链表元素相当于倒置,所以最后的结果还是打乱了插入的顺序,所以1.8之后干脆直接换成尾插放弃热点数据策略的使用了。
6-2 假设你有一批历史积分数据要存储,数量在kw条左右 存入mysql 你的方案是什么
? ? ? 对于海量数据存储到数据库,我们的解决方案有很多如:分区,分表,分库,集群等。首先,对这些数据按照某种规则进行分区,把表数据文件拆成多个文件存储,逻辑对外是一张表,突破单表上限,提高查询删除和统计效率;
? ? ? 然后就是分表:分表又分为垂直分表和水平分表,垂直分表应用于当表中字段过多,单行体积过大,表体积也会很大,比如说当文章表包含文章内容的时候,影响数据库的查询效率,可以进行垂直分表,解决单表字段过多和数据过多问题。水平分表主要解决数据表字段均衡但是每条数据不同并且数据量很大,可以进行水平分表,比如说根据赛季分表
? ? ? 再然后就是分库和集群:当系统对数据库的并发量很大的时候,单个数据负担过大且磁盘空间有限,就可以进行分库和集群,根据不同微服务进行分库,每个微服务使用独立的库。为了保证单节点的高可用性,我们会给数据库建立主从集群,将数据库分为读库和写库,写库只负责数据修改更新和删除,读库负责查询,然后写库将数据同步给读库。
6-3 请你说一说你的排行榜功能是如何实现的
排行榜功能是将用户总积分保存到redis中来实现的
? ?首先当用户获取积分后,将积分数据根据年月作键,用户Id作为值,使用Zset的incrementScore增加并存储到redis的zset中的score ?根据score自动排序,当查询排行榜的时候,根据是否查询当前赛季,通过key来分页查询redis中的对应排行榜,然后返回前端展示。
以上就是排行榜功能的具体实现。
6-4 历史赛季积分是如何生成的?
? ? ? ?历史赛季积分的生成主要通过xxl-job定时任务和任务链来实现的,大致流程如下 ,由于历史赛季积分榜需要由redis持久化到mysql,因此需要创建表来保存数据,首先考虑到榜单数据量过大,单表无法满足存储需求,因此xxl-job主任务(生成积分表单)会在固定时间根据每个赛季来创建一张数据表; 其次主任务的子任务(榜单数据持久化)将redis数据转存到mysql里面;然后呢榜单数据持久化的子任务(清理redis上赛季缓存任务)删除redis缓存数据; 这样使用xxl-job的一条完整的任务链就形成了,我们的需求得以通过任务链完成。