北京掌上先机一面技术总结
北京掌上先机------第一次技术面试总结
自我介绍
面试官询问实习时间:说得3个月左右。
项目是自己找得课设的一个商城项目,因为简历递交给公司时比较早,没有太多时间自己动手从0-1实现一个完整的项目。
项目提问:
1.这个是你独立完成的吗?
2.商城的订单管理(个人觉得说东西很多,找一个小的切口来谈比较好,其实这块主要是面试挂的提问,引导很多)
1.有解决商品下单的并发问题?
下单这一举动对用户是比较明确的?
引言:在商城管理系统中,处理商品下单的并发问题确实是一个关键挑战,特别是在高并发场景下,确保订单的正确性和数据的一致性至关重要。乐观锁是一种常用的解决并发控制的方法,尤其适用于读多写少的场景,它假设并发冲突不常发生,只有在更新数据时才会检查冲突。
那我来谈一谈乐观锁在商品下单中的应用吧
(1)首先用户发起下单请求,系统首先读取商品信息,包括库存数量等
(2)检查库存:在乐观锁的机制下,这一步通常不是严格必要的,因为乐观锁会在更新时检查冲突,出于用户体验和性能考虑,可以在前端或者应用层做个预检查。
(3)生成订单
(4)使用乐观锁来更新库存
在数据库中,为商品添加一个版本号version或者时间戳(timestamp)字段作为乐观锁的标志。
当系统尝试扣减库存时,会读取当前商品的库存数量和版本号。
在更新库存时,除了设置新的库存数量外,还会检查版本号是否匹配。如果版本号匹配,说明此期间没有其它事务修改过这条记录,更新成功;如果不匹配,说明有其他事务已经修改了这条记录(即发生了冲突),更新失败。
(5)处理并发冲突:如更新库存时发生并发冲突,系统可以采取不同的策略来处理:比如重试下单操作、提示用户库存不足或者稍后再试等。
(6)完成订单的创建:如果库存更新成功,将订单状态更新为已创建或者相应状态,表示订单已经生成成功。
优缺点 优点
- 实现简单,不需要像悲观锁那样锁定资源,提高了系统的并发性能。
- 适用于读多写少的场景,能够减少锁竞争。
缺点
- 在高并发写操作的场景下,乐观锁可能会频繁失败,导致用户体验下降。
- 乐观锁依赖于数据库的事务支持,如果事务回滚频繁,可能会对数据库性能产生影响。
2.面试官的建议:有考虑过用企业消息中间件来解决并发问题吗?比如削峰?因为用户的操作只会在某一段时间内并发特别高?
【用消息队列来处理一些高并发的问题】
3.业务场景题:如何避免用户重复下单(多次下单未支付,占用库存)
如果一个用户多次下单,可能会锁库存或者损坏其他用户权益,因此需要考虑用户重复下单。
(1)首先前端可以进行按钮控制
用户点击“下单”按钮后----------->按钮状态变为“处理中”或者“请稍等”
但是前端的操作无法完全避免重复请求,因此需要与后端的幂等控制结合,因此确保不会因为多次点击创建多个订单。
(2)在每次下单请求中生成唯一的requested-Id或者token。
用户进入订单也面前,前端会请求后端生成这次请求的唯一的request-Id和token,然后每次下单请求中带上这个唯一的request-Id或者order-Token。这样后端就可以检测该标识是否存在,来决定是否创建新的订单。
(3)分布式锁+判断+下单
1.用户维度,加上分布式锁,例如分布式锁的key中内容可以是xxx+User-Id,这样同一个用户的操作就会被锁定。
2.判断用户是否有在流程中未支付的订单。
3.如果没有则正常进行下单流程。
4.如果有则直接返回,提醒前端您还有未支付的订单,请先支付后再继续下单。
扩展知识:
实现幂等控制:确保系统在面对重复请求时能够保持数据的一致性和正确性的重要手段
常见的实现方式:基于唯一索引实现 基于Token机制 基于乐观锁机制 基于分布式锁机制(通过串行化请求处理来实现幂等------》适用分布式系统的并发场景)
电商项目中:唯一索引实现幂等约束
为每个订单请求设置一个request-Id或者order-Token。
具体是在订单数据库中保存唯一的标识,建立唯一索引。当新的订单请求到达时,首先检查数据库中是否有相同的标识订单记录,如果有则直接返回订单信息,避免重复创建。
唯一索引实现幂等约束的局限性
1)业务逻辑需要依赖异常(异常的性能开销----------比如说创建成本高,捕获过程耗时, 代码的可读性不好,有时候不便于分辨什么是正常流程,什么是错误处理)
2)数据库会有一定的压力(把重复的请求都要靠数据库来做唯一判断)
4.业务场景:你是怎么解决一个商户不超卖的情况?就比如说一个商户挂上的库存只有20件,在一些购买量比较大的情况下,你是怎么解决让用户卖得不超过21件?
技术手段:
1.分布式锁:在高并发场景下,使用分布式锁确保同一时间内只用一个请求能操作库存,避免多个请求同时扣减库存导致超卖。
2.延迟消息机制:通过消息队列(如Rocket-MQ)设置延迟消息,在订单提交后延迟一段时间(如10分钟)再次检查订单状态。
3.定期对账与监控:定期对库存数据进行核对,确保系统中的数据库存与实际库存一致。如果发现少卖或者超卖情况,及时调整库存。
5.数据库锁的如何减少使用
如果造成了插入或者删除过程中这个锁,你get到了这个锁。由于某些不可控原因,这个锁一直卡在那儿,其他用户下不了单的。在这种双十一的情况下是十分致命的,因为一锁可能是锁的某个表而不是某一行啦。这块有想过怎么去避免这种问题。
面试官建议:锁前置,在业务层去实现锁,而不是在数据库层面去实现?这样只会影响某一个用户的某一单,而不会影响所有用户。
面试官给得答案:直接使用Redis锁来解决这个问题,因为当用户下单肯定要检测它的库存量,这部分的数据实际上是可以同步到Redis中的。
6.电商还有一个:如果商品的数据和订单的数据十分庞大,如果让我做订单数据的分库分表?如何去分呢?订单的量会非常的大,随着用户一直下单,不可能放在一张表里面。那么现在如果有两种分库分表的模式,一种是基于用户的,另外一种是基于商品的,如果是你,如何选择?
参考答案:两种方式都是可以的,根据具体的业务需求和查询模式来决定。言之有理即可。
组成语言是Java吧,那就问问java基础知识吧
1.平时编程里面有用过泛型吗?(挺重要的一个问题)
Java中的泛型是一个强大的编程特性,用于在编译时提供类型安全性和代码复用性。
泛型允许开发者在定义类、接口和方法使用类型参数,从而可以指定这些结构可操作的类型,而不是具体的类型。
常见用途:
集合框架:如ArrayList、HashMap<K,V>
**数据结构:**自定义数据结构(如栈、队列、链表)可以使用泛型来实现通用性。
算法实现(看是否有了解吧):泛型方法可以实现通用算法,如排序、搜索。
2.JVM是如何实现泛型的?
(在这里点评一下:慧策技术面试官人真好,给出了一点提示答案:泛型擦除有了解吗?
但是我不知道,没有听过,面试官朝我笑了笑,那行吧。
面试结束后总结发现面试官引导了我不少,谢谢他的理解与包容!)
3.多线程应该用过吧,那你平时使用多线程一般会怎么使用呢?
比如有这样一个业务场景:要你使用多线程异步处理这个任务,你会去怎么呢?
我回答了:线程池 异步的编程 显示锁
线程池是比较经常用得,所以面试官继续提问我线程池。
继续提问:有使用过线程池吗?
回答:有用过一点,以为能够躲过一劫,没有问我怎么样使用线程池的。而是问了我线程池的一个场景题。
那比如我new了一个线程池,最大浮动线程数是5,等待队列是1000,如果它的等待队列也满了,那我再提交这个任务,会发生什么事呢?
事后再看这个问题,面试官应该是考察我对线程池的组成部分是否熟悉。线程池里面有个拒绝策略,这个我猜测应该是面试官心怡的答案。
4.MySQL经常用吧?(主要是对索引,查询条件的提问)
4.1我现在有三个字段,字段上有联合索引,现在查询条件是where a = 1 and b = 1 or c = 1,像这样一个查询条件能不能用上联合索引呢?
我回答:部分可以使用
面试官:嗯嗯,哪一部分能用,哪一部分不能用。(应该是蒙对了,面试官想听一听自己的分析)
继续追问:4.2那如果只有一个字段,只有a这个字段,a里面有null值,会不会影响它走索引的效率?
答案:a字段里面有null值不会影响它走索引的效率。
继续提问:4.3那如果是这样的一个查询条件:a!=1,像这样的一个情况,a字段如果有null值能不能被查出来呢? 回答:我不是很了解。答案是不能排除出来。
面试官一句:我的问题就这些了吧,你有什么疑问吗?
自我感觉回答得稀碎,面试官说得最多得就是ok,行。
因为自己还是想争取进入公司实习,就还是问了问吧。
反问:
1.我如果进公司,大致是做是什么样的任务分配或者说公司的业务是什么?
公司目前是To-b的电商业务,针对企业用户是做一些电商服务。
2.如果我去那边的话,人员是怎么分配的?
目前一般新人进来,我们一般会让你去优化线上的一些问题。
第一周:让你去优化一些点,或者优化线上的一些bug。通过优化这些bug,让新人去了解一下公司的业务。
第二周:我们一般会给新人一些小的需求,完成一些小的功能。
3.鼓起勇气,知道回答得稀碎,还是希望征求一下技术面试官得学习建议吧
(1)说我项目经验欠缺,做得电商项目存在很多的不足,完全上不了线的。
(2)可以看一看GitHub上那些好的电商项目是怎么做得,人家是怎么处理这些问题的。而不是说,现在有很多那种培训班,或者黑马程序员的教程课,对着项目敲一遍,没有自己的思考,很多东西他只是为了一个基础的教学,很多东西他没有让你思考的地方。面试官指出:比如说我刚刚和你聊得订单库存的那个问题,自己要去思考怎么做。
反思与总结:
(1)自己要动手做些一些项目,因为这样自己熟悉项目,靠编造得项目(混面试)其实很难说服面试官的。 (2)基础知识一定要夯实一点,就比如:my-sq-l后面的几个小问题,看似复杂,其实再理一理,好像还行吧。自己对于联合索引这块的题目也不是很了解。
(3)心态很重要的,面试其实也有点看运气的。因为每个面试官的侧重点不一样,有得倾向于项目,有得侧重基础知识的提问,还有得两者都要兼顾。所以自己还是要认真,耐心准备吧,尽自己的努力。
(4)谈谈面试官吧:可能深受面试的我,觉得是一种煎熬,很多问题都是一脸的茫然。但是事后,自己再慢慢回味面试的过程,发现面试官引导了我很多,可能说得比我还要多。(面试官的ok,行一直挂在嘴边,可能也是为了让我不那么紧张吧)
(5)最后一点:自己的口头表达能力有点欠缺,沟通能力需要提升一点。很多时候等面试官说完,再给出自己的见解,抢着回答这个行为不是很好哈~
