业务:第六天

本文讨论了HashMap和ConcurrentHashMap在Java中的区别,重点介绍了1.7和1.8版本的底层结构差异以及如何选择在高并发场景下使用。同时,文章还涉及MySQL的表分区、分库分表策略,以及排行榜功能的实现,包括实时榜单用Redis和历史榜单在MySQL中的水平分表设计。
摘要由CSDN通过智能技术生成

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

HashMap和ConcurrentHashMap是Java中Map集合,区别点是

  • HashMap:非线程安全。
  • ConcurrentHashMap:线程安全。
    • 1.7版本:ConcurrentHashMap主要由Segment(数组)+ HashEntry(链表)组成,同时采用分段锁机制保证现高并发的线程安全
    • 1.8版本:ConcurrentHashMap主要由Node数组+链表和红黑树构成,抛弃了分段锁,采用 CAS + synchronized 保证线程安全。
  • 项目中不采用HashTable是因为使用synchronized对整个数据结构锁定,锁的粒度大,任何读或写操作都极大的影响性能。
  • 分段锁:将整个集合分成多个小的Segment,每个Segment拥有自己的锁。简单说,就是缩小每次锁的 数据的数量。
  • CAS:乐观锁。
    • 例如:put操作会根据当前 key 定位 Node,如果为空表示当前位置可以写入数据,则先利用CAS尝试写入,失败则使用自旋锁保证成功
  • synchronized:悲观锁。在扩容操作时,为保证对旧数组安全的读和写,会使用synchronized来保证线程安全。
  • 自旋锁:一种基于忙等待的锁,当一个线程尝试获取锁时,如果锁已被其他线程占用,该线程不会被挂起,而是会循环检查锁的状态直到获取到锁为止

假设你有一批历史积分数据要存储,数量在千万条左右,需要存入MySQL 你的方案是什么?

MySQL5.1开始支持表分区功能。我们可以通过分库、分表的设计方案来对这些数据进行存储。

分区指的是按照某种规则,把表数据对应的ibd文件拆分成多个文件来存储

分表:在创建表时按照业务需求对表进行拆分。此时无论是逻辑上,还是物理上,就从一张表变成了多张表来存储数据。

  • 水平分表:将同一张表,通过规则拆分为多张表。
  • 垂直分表:按照字段拆分表的方式,称为垂直拆分。

引发的问题:

  • 增删改查时,需要自己判断访问哪张表。
  • 垂直拆分还会导致事务问题及数据关联问题:单表操作变为多表操作

分库:保证数据库的高可用性

  • 垂直分库:按照项目模块,给项目分配到的每个库中的表是不同的,这种分库模式成为垂直分库
  • 水平扩展:给数据库建立主从集群,主节点向从节点同步数据。两者结构一样,可以看做是水平扩展

引发的问题:

  • 成本高、数据聚合统计比较麻烦、需要考虑主从同步的一致性问题和分布式事务问题

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

排行榜是根据积分实现的,分为实时榜单和历史榜单,同时榜单按月份划分。

  1. 实时榜单:读写操作频繁。所以存到了reids的zset结构中,当前月份做key、用户id做为value、积分做为分数,实现排行。

  2. 历史榜单:数据量大,查询量小。所以从redis同步到了MySQL中,同时为防止单表数据量过多,采用了水平分表的设计方案,把一个赛季的榜单放在一张表中,查询则根据赛季标识只查一张表即可。

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

历史赛季积分的生产分为3大步,核心是把Redis中的上赛季数据,同时采用水平分表的设计方案保存到MySQL中。

  1. 利用定时任务,定期在月初,根据上赛季的时间在MySQL中创建新的历史榜单,
  2. 之后将redis中的数据同步到这张表
  3. 最后清理redis上赛季的缓存

因为这三步都是采用定时任务来完成的,所以采用了定时任务的任务链来完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值