[Java场景题总结]持续更新

一个外卖平台上有一个外卖单子,现在有多名骑手想接这一单,如何保证只有一个骑手可以接到单子?

用Redission事务避免超售。
乐观锁。

如何把一个文件快速下发到100个服务器?

树状:

  1. 每个服务器既具有文件存储能力也应具有文件分发能力。
    1. 每个服务器接收到文件之后向较近的服务器分发,具体类似多叉树,应该挺快的 (p2p)

索引状:

  1. 设置1000个缓存服务器,文件先下发到这些缓存上。(具体多少缓存、分几层缓存和具体业务有关。)
  2. 每个缓存服务器接收1000个服务器取文件。

典型TOPk系列的问题:10亿个数,找出最大的10个。等(10万个数,输出从小到大?有十万个单词,找出重复次数最高十个?)

让你设计一个微信发红包的api,你会怎么设计,不能有人领到的红包里面没钱,红包数值精确到分。

分布式集群中如何保证线程安全?

串行化(隔离级别,其实不可行 过于严格了)
有的时候可以通过串行化可能产生并发问题操作,牺牲性能和扩展性,来满足对数据一致性的要求。比如分布式消息系统就没法保证消息的有序性,但可以通过变分布式消息系统为单一系统就可以保证消息的有序性了。另外,当接收方没法处理调用有序性,可以通过一个队列先把调用信息缓存起来,然后再串行地处理这些调用。

分布式锁
为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:

  • 互斥性。在任意时刻,只有一个客户端能持有锁。
  • 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
  • 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
  • 加锁和解锁必须具有原子性。

设置setNx ,这里可以看八股文那里。无外乎就是加锁的过期时间,每把锁加一个uuid,通过判断后删除锁,交给redission实现即可。

问题:删除操作缺乏原子性。

在判断是自己的uuid 后准备删除 这时候正好过期,被另一个线程拿到了这把锁。

也会误删 所以需要使得判断和删除时原子性的,可以使用Lua脚本实现判断和删除操作的原子性。

有一张200W数据量的会员表,每个会员会有长短不一的到期时间,现在想在快到期之前发送邮件通知提醒续费,该如何实现?

1、系统部不主动轮询,每当用户登录到系统后,触发一次检查。如果发现会员过期时间小于设定的阈值(或者当前时间吧),规避了轮询问题。不会对数据库和后端应用程序造成任何压力

缺点:如果用户一直不登录,就一直无法实现会员过期,并且也无法提前去跟进运营策略发送邮件或续期的提醒消息。

2、使用ES搜索引擎:

优点:在于大数据量的快速检索,并且具有高可扩展性(Scalability)和高可靠性(reliability),非常适合大规模数据的处理

3、用redis缓存用户ID和会员过期时间,使用redis的过期提醒功能。

notify-keyspace-events 改为 notify-keyspace-events “Ex” 会触发一个key的过期事件

缺点:如果缓存被击穿了 ,那么这个功能就完全谈不上可靠。

4、使用MQ的延迟队列,来触发。

在2G大小的文件中,找出高频top100的单词?

先把大文件分割成小文件。比如把2g分割成2048个512KB的小文件,定义一个长度为2048的hash表数组,用来统计每个小文件中单词出现的频率。我们可以用多线程来处理这2048个小文件,然后用Hash取模运算算出来单词的hash值,存储到hash表数组当中。再遍历这2048个hash表,把频率前100的单词存入到小顶堆里面,就可以获得top100的单词了。

int hash = Math.abs(word.hashCode() % hashTableSize);
hashTables[hash].merge(word, 1, Integer::sum);

对接第三方接口要考虑什么?

1、安全性问题

2、接口的稳定性和可靠性

3、接口是否存在访问限制或费用

表数据量大的时候,影响查询效率的主要原因有哪些?

1、磁盘IO

2、索引失效。可能原因是查询条件中使用了不支持索引的操作符,或者数据分布不均匀导致索引失效。

数据库索引可能在以下多种情况下失效,导致查询效率降低甚至全表扫描的发生:

  1. 前模糊查询(LIKE操作):当使用LIKE操作符进行查询,且通配符 % 出现在字符串的开始位置时(如 LIKE '%keyword'),索引通常无法被利用,因为数据库无法通过索引来定位匹配项。
  2. 数据类型不匹配:如果查询条件中使用的数据类型与索引字段的数据类型不一致,可能导致索引失效。例如,对字符串字段使用整型参数进行比较。
  3. 函数操作:在查询条件中对索引字段进行函数运算(如 LOWER(column)SUBSTR(column)),数据库无法直接利用原始索引,因为索引是基于字段的原始值建立的。
  4. 联合索引中断:当使用联合索引时,如果查询条件没有覆盖索引的最左前缀,或者在索引字段间有范围查询(如 WHERE column1 = value AND column2 > value),可能造成索引部分或全部无法使用。
  5. OR条件:当查询条件中包含OR操作符,且OR两边的字段只有一个是索引字段时,索引可能无法被有效利用,尤其是当OR两侧的条件分别使用了不同索引时。
  6. NOT操作:NOT操作可能导致索引失效,特别是当与范围查询结合使用时,因为数据库优化器可能无法确定有效的索引使用策略。
  7. 子查询和多表连接:在复杂的子查询或多表JOIN操作中,如果连接条件或子查询的执行计划不理想,可能导致相关索引未被使用。
  8. 索引列参与计算:在查询条件中,如果索引列参与了计算表达式(如 column + 1 = value),索引可能无法发挥作用。
  9. 大表更新频繁:索引在数据频繁更新的表上可能需要不断重建或更新,这可能导致索引暂时不可用或效率降低。
  10. 索引列数据分布不均:如果索引列的值分布极度不均匀,可能导致索引选择性差,数据库引擎可能放弃使用索引。

3、数据分页

4、锁竞争。当多个事物同时对同一个表进行读写操作时,就会产生锁竞爭,而锁竞争会导致查询效率下降。

快照读实现细节

  1. ReadView: 在InnoDB中,快照读是通过创建一个名为ReadView的内部数据结构来实现的。ReadView记录了当前活跃事务的ID列表,以及系统中已分配的最大的事务ID。当执行快照读时,数据库会使用这个ReadView来判断每一行数据对于当前事务的可见性。
  2. 版本链: InnoDB为每行数据维护了一个版本链,记录了该行数据在不同事务修改下的多个版本。当进行快照读时,会根据ReadView找到符合条件且对当前事务可见的数据版本。
  3. 隔离级别: 快照读的行为与数据库事务的隔离级别密切相关。在可重复读(Repeatable Read)隔离级别下,事务内所有的查询都基于同一个快照;而在读已提交(Read Committed)隔离级别下,每次查询都会生成一个新的快照。

减少锁争用: 由于快照读不加锁或只加较少的锁(如在某些隔离级别下),可以显著减少读写操作之间的锁竞争。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值