滴滴java后台面经

总共三面,都主要根据简历上的项目来问的。

一面

1. 描述秒杀系统的秒杀逻辑过程?

1)首先秒杀系统中有商品列表页和商品详情页,当用户在商品列表页点击想要秒杀的商品,会跳转到商品详情页,商品详情页会有一个倒计时,如果未到秒杀时间或者秒杀时间结束或者商品已卖完,立即秒杀的按钮是灰的,不能点击的。

2)如果到了秒杀时间,用户点击立即秒杀的按钮,请求到达后端后会先判断用户是否登录(从cookies中读取sessionId,并去redis中通过sessionId查找用户信息),如果没有登录,则返回登录页面。

3) 如果登录了,则判断是否为此用户和此商品生成过秒杀路径(redis中是否有记录uid_gid),如果没有,则为此用户生成一个随机的uuid并MD5加密后添加到秒杀路径中作为此用户的专有秒杀路径,将uid_gid作为key,path作为value放入redis中。

4)用户通过此秒杀路径向后端发起秒杀请求,后端校验此path是否与redis中记录的一致。一致的话判断此商品在redis中的记录的库存是否>0。然后判断是否为此用户此商品减过库存(看redis中是否记录过),没有的话就判断redis中是否存在此用户购买此商品的订单,也没有的话就执行预减库存,即先将redis中此商品库存减1,并记录为此用户减过此商品的库存。

5)将秒杀消息放入消息队列,主要是用户id和商品id,一直监听消息队列的消费者线程执行sql减库存,sql语句中也会判断库存是否大于零,并生成订单记录,减库存和生成订单是在一个事务中。

6)前端使用ajax不断轮询订单生成状态(result=0表示排队中),若result = -1说明失败,直接返回秒杀失败。直到查到了订单id,则把订单放入redis中,并在前端显示出来。

2. 怎么防止超卖?你使用的什么缓存更新策略?

读的时候是先读缓存,缓存中没有再读数据库,并放入缓存中。

写的时候有两种策略,一种是先删除缓存中数据(一般来说直接删除缓存中的数据会比更新数据快),再更新数据库,这种策略高并发情况下频繁地更新同一行数据容易使流量都直接走数据库了,相当于缓存没用。而且当数据库还未更新完时,又来了新的请求读取同一行记录,会又把旧值放入缓存中。所以在减库存时,是先在redis中预减库存,然后消费者异步地去数据库中减库存,可能会出现缓存与数据库中数据不一致的情况,但不会出现超卖现象。

另外一种是先更新数据库,再删除缓存,但若数据库更新完了,缓存还没来得及删除,也会使得读到的是缓存中的旧值。

3. 如果redis宕机怎么办?

首先redis可使用主从架构+哨兵机制,从服务器的数据从主服务器中复制过来(分为两步:完整/部分重同步,命令传播:主写入后通知从也写入),让哨兵监视所有的redis服务器,当主挂了,就执行主备切换。

其次redis有持久化机制,基于快照的RDB方式和AOF(append-only-file)方式,如果真的挂了还可以从磁盘中还原数据。当redis恢复数据时,应使用本地缓存+限流方式保护数据库不被高并发的流量压垮。

4. 怎么保证消费者取任务的顺序性?

只用了一个队列,是direct类型的,队列中的binding_key与消息头中的routing_key一样时,消息会被路由到这个队列。消费者每次从这一个队列取出消息消费,肯定是按顺序的。

5. 那如果排队的任务太多,一个队列放不下怎么办?

使用多个队列,根据商品id将相同id的商品路由到相同的队列。

6.如果url有加参数,参数的顺序可能不同,这种情况怎么对url去重?

取出参数排序后再拼接,再放入HashMap中去重。

7. hd钱包的密钥管理,怎么在树中查到到一个密钥是否是由主密钥生成的?

会有路径的记录。

8.如果没有路径,怎么搜索,而且数据量巨大?

可以使用布隆过滤器记录私钥。

9.算法:实现一个lru缓存

10.操作系统的内存管理,一个进程怎么知道自己能使用多大内存空间?

进程无需知道自己能使用哪些地址,进程认为自己能使用所有的虚拟内存空间,具体使用的物理内存,有操作系统实现。

11.ip包怎么实现差错控制?

通过校验和

12. ip路由寻址是成环了怎么办?

跳数有限制,最多只能16跳。

你可能感兴趣的:(求职面经,java后台,滴滴,面经,java后台,秒杀系统)