第六天业务题

本文讨论了HashMap和ConcurrentHashMap在Java中的差异,包括线程安全、性能和迭代器特性。同时介绍了在处理大量历史积分数据时,如何使用分库分表和Redis存储,以及排行榜功能的实现方法和历史赛季积分的生成过程。
摘要由CSDN通过智能技术生成

6-1 HashMap和CurrentHashMap的区别是什么? CurrentHashMap底层结构在1.7和1.8有什么不同?

HashMap 和 ConcurrentHashMap 是 Java 中用于存储键值对的两种不同的 Map 实现,它们之间有一些重要的区别:
1、HashMap 不是线程安全的,ConcurrentHashMap 是线程安全的;
2、在单线程环境下,HashMap 的性能可能会比 ConcurrentHashMap 更好,在高并发环境下,ConcurrentHashMap 的性能通常会比 HashMap 更好。
3、HashMap 的迭代器(Iterator)是 fail-fast 的,即在迭代过程中如果有其他线程对 HashMap 进行结构上的改变,会抛出 ConcurrentModificationException 异常。ConcurrentHashMap 的迭代器是弱一致性的,它允许在迭代过程中进行修改操作,但不保证一定能获取到最新的修改结果。

在JDK 1.7中,ConcurrentHashMap使用了分段锁(Segment),每个Segment维护了一个HashEntry数组,不同的Segment之间相互独立,这样可以在多线程并发的情况下减少锁竞争,提高了并发性能。但是在高并发的情况下,仍然存在一定的锁竞争和开销。
在JDK 1.8中,ConcurrentHashMap底层的实现进行了重大改进。引入了CAS操作和Node节点,使用了更细粒度的锁控制,减少了锁的竞争,提高了并发性能。此外,JDK 1.8中的ConcurrentHashMap还引入了红黑树来优化查找操作,进一步提高了性能。

6-2 假设你有一批历史积分数据要存储,数量在kw条左右 存入mysql 你的方案是什么

对于数量在千万级别的数据,我会考虑使用分库分表来实现。
1.针对历史积分数据,我会按照时间范围进行分片。例如,可以根据年份进行分库,然后在每个库中根据月份进行水平分表。
2.根据设计好的分库分表策略,创建相应数量的数据库实例和表结构。例如,如果按照用户ID分库,可以创建多个数据库实例,每个实例存储一部分用户的数据;然后在每个数据库实例中,按照时间范围创建多张表,每张表存储一段时间内的积分数据。
3.将历史积分数据按照分表规则插入到相应的分表中。可以使用INSERT INTO语句将数据插入到指定的分表中。
4.在查询积分数据时,根据分表规则确定需要查询的具体分表,然后使用UNION ALL操作将多个分表的数据合并起来进行查询。可以使用子查询或者程序中动态生成查询语句的方式来实现。

6-3 请你说一说你的排行榜功能是如何实现的

我们的排行榜主要有两块,一个是当前赛季,另一个是历史赛季,当前赛季指的就是当前月,按照每个用户获得积分的数量倒序统计排行,如果把当前赛季的数据存到MySQL的话,当用户量过于庞大时,新增积分的途径众多,就导致数据库的修改过于频繁,大大增加了数据库的压力,于是我考虑把当前赛季的积分数据用ZSet存到Redis里,用当前的月份命名当作key,用户id作为value,用户当月的积分作为score,在查询排行榜时,参数中有一个参数赛季标识,当赛季标识为空,我们认定是查询当前赛季,去Redis里查询数据;如果不为空,就会去MySQL查询历史排行榜,以上就是排行榜功能的实现。

6-4 历史赛季积分是如何生成的

首先,在MySQL里创建对应的存储历史赛季积分的表,一般一个赛季会对应一个表,由于涉及到Redis和MySQL的数据更新操作,为了保证业务逻辑按顺序执行,使用xxl-job构建一个任务链,并使用子任务,在每个月一号的凌晨,把Redis中的数据存到MySQL中,最后清空Redis里的数据即可。

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值