【印象深刻------美团优选】美团凉后,【美团优选】捞起【查漏补缺,应用场景,底层欠缺】

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 【印象深刻------美团优选】美团凉后,【美团优选】捞起【查漏补缺,应用场景,底层欠缺】

一、面试概况


今天是之前面美团java研发凉之后的,美团后端捞起面试,我之前一直是觉得自我感觉良好的,【感觉技术面以及四门专业课=====从来不虚】,结果今天感觉非常的知足,不是说的笔试和面试怎么杨吧,就是我在今天这场面试中,积攒到了很多经验,找到了自身的不足,应该思考的地方,面试的要点,让我很是受益,所以抓紧做一个笔记。


二、面试-笔试


两个算法:

一个是二叉树的先序遍历【做出来了】

合并两个有序数组【也做出来了】


三、技术面


3.1 Redis【一直在干redis连环炮】

3.2 说一下redis为什么快?


我说基于内存,基于单线程,然后网络请求有IO多路复用所以很快。

1、完全基于内存

2、数据结构简单

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路 I/O 复用模型,非阻塞 IO;


3.3 redis如何保证数据的一致性?


我说了个集群 分区数据同步一致性,因为真的想不到了


3.4 redis的锁机制


1.Redis中可以使用SETNX命令实现分布式锁

当且仅当 key 不存在,将 key 的值设为 value。 若给定的 key 已经存在,则 SETNX 不做任何动作

2.RedLock

安全特性:互斥访问,即永远只有一个 client 能拿到锁

避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区

容错性:只要大部分 Redis 节点存活就可以正常提供服务

3.redission

Redisson是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。


3.5 redis的事务【redis 事务不保证原子性,不支持回滚】


Redis 事务的本质是通过MULTI、EXEC、WATCH等一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序 串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中

1.单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断

2.没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行

3.不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令

1.事务开始 MULTI

2.命令入队

3.事务执行 EXEC


3.6 redis的五大数据类型


String,List,Set,Zset,Hash


3.7 redis的5大数据类型的使用场景


6ac94432d2904ecd87aec2ba89d5977d.png


1.String 进行自增自减运算,从而实现计数器功能,很适合存储频繁读写的计数量

2.list: 可以通过lpush/rpush rpop/lpop 读取和写入消息,实现阻塞队列

3.Set 可以实现交集、并集等操作,从而实现共同好友,推荐等等功能

4.ZSet 可以实现有序性操作,从而实现排行榜等功能。


3.8 redis的list 与 set的区别?


413826993e37497db5a2ddb4524e522a.png


3.9 redis的String底层怎么实现的?list、set,hash的底层怎么实现?


1.String的数据类型是由SDS【简单动态字符串】实现的,C语言的实现方式有专门用于保存字符串长度的变量,所以可以在O(1)时间内获得

2.链表是list的实现方式之一。当list包含了数量较多的元素,或者列表中包含的元素都是比较长的字符串时,Redis会使用链表作为实现List的底层实现。此链表是双向链表。

链表结构的特点是可以快速的在表头和表尾插入和删除元素,但查找复杂度高,是列表的底层实现之一

3.Hash:数组 + 链表(采用头插法解决冲突,不会像java语言的map一样转化为红黑树),redis会把kay、value封装成一个dictEntry的结构体(dictEntry的key为string类型,value是一个指针,指向一个redisObject对象(不像java语言一样把hashmap的key、value的具体值封装在一起))

3.list底层实现:底层是链表,有两个list,一个是ziplist,字面意是压缩列表,另一个是quicklist,字面意是快速列表,在redis中直接使用的是quicklist.

4.set底层实现: Set是一个特殊的value为空的Hash

5.zset底层实现:Zset底层是一种跳表SkipList数据结构(跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找,实质就是一种可以进行二分查找的


其实跳表主要是来替代平衡二叉树的,比起平衡树来说,跳表的实现要简单直观的多。

跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速查找访问节点的目的。跳跃表是一种随机化的数据,跳跃表以有序的方式在层次化的链表中保存元素,效率和平衡树媲美 ——查找、删除、添加等操作都可以在O(logn)期望时间下完成


aeef576e5d71490eac3b71f612e6c56a.png


3.10 在使用场景中怎么区别 list 与 set ?


2.list: 可以通过lpush/rpush rpop/lpop 读取和写入消息,实现阻塞队列

3.Set 可以实现交集、并集等操作,从而实现共同好友,推荐等等功能

4.ZSet 可以实现有序性操作,从而实现排行榜等功能。


3.11 Redis的内存用完了?


1.Redis支持运行时通过命令动态修改内存大小

2.Redis的内存淘汰

0a3e260dcdff40aab2f8dd1e68aecc0b.png

3.12 redis的那些命令是原子性的?

46ba079301004581b094957d6a3e6c4a.png


3.13 RDB && AOF


RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。

优点:使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能

缺点:RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候redis.conf


AOF:将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已经写入到文件或者即将写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当server需要数据恢复时,可以直接replay此日志文件,即可还原所有的操作过程。AOF相对可靠,它和mysql中bin.log、apache.log、zookeeper中txn-log简直异曲同工。AOF文件内容是字符串,非常容易阅读和解析。

AOF默认关闭,开启方法,修改配置文件reds.conf: appendonly yes


优点:可以保持更高的数据完整性,如果设置追加file的时间是1s,如果redis发生故障,最多会丢失1s的数据;且如果日志写入不完整支持redis-check-aof来进行日志修复;。AOF的特性决定了它相对比较安全,如果你期望数据更少的丢失,那么可以采用AOF模式

缺点:AOF文件比RDB文件大,且恢复速度慢。


四、Mysql


4.1 说一下Innodb引擎


简单


4.2 说一下mysql的锁机制


悲观锁

在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)

如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定。

如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。

其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。


优点和缺点

优点:安全

缺点:悲观锁实际上是采取了“先取锁在访问”的策略,为数据的处理安全提供了保证,但是在效率方面,由于额外的加锁机制产生了额外的开销,并且增加了死锁的机会。并且降低了并发性;当一个事物所以一行数据的时候,其他事物必须等待该事务提交之后,才能操作这行数据。


乐观锁

相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。

相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本


乐观锁的优点和缺点

乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。但如果直接简单这么做,还是有可能会遇到不可预期的结果,例如两个事务都读取了数据库的某一行,经过修改以后写回数据库,这时就遇到了问题。


4.3 说一下如何排查慢SQL

1.mysql默认不开启慢SQL日志,检查是否开启了 慢查询日志 :
show variables like '%slow_query_log%' ;
2.开启慢SQL
/etc/my.cnf 中追加配置:vi /etc/my.cnf 
    [mysqld]
    slow_query_log=1
    slow_query_log_file=/var/lib/mysql/localhost-slow.log
3.查询超过阀值的SQL
show global status like '%slow_queries%' ;
4.慢查询的sql被记录在了日志中,因此可以通过日志 查看具体的慢SQL。
cat /var/lib/mysql/localhost-slow.log
5.通过explain分析sql语句,例: 
explain select name from tablex where a = '1';

898d023cd7674b1094dce4bf38c509f8.png

4.4 说一下mysql悲观锁与乐观锁的使用场景?


悲观锁:比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量。

乐观锁:比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。


总结:两种所各有优缺点,读取频繁使用乐观锁,写入频繁使用悲观锁。


五、JVM


5.1 说一下在什么情况下,对象会进入老年代?


1.大对象

2.长期存活的对象 s0 s1 15岁以后【只答出来这个】


5.2 说一下为什么 s0区 = s1区


没答出来


5.3 如果java程序CPU过高,如何排查????


进程====》定位线程

一般java应用cpu过高基本上是因为

1.程序计算比较密集

2.程序死循环

3.程序逻请求堵塞

4.IO读写太高


1、先通过top命令找到消耗cpu很高的进程id假设是123
2、执行top -p 123单独监控该进程
3、在第2步的监控界面输入H,获取当前进程下的所有线程信息
4、找到消耗cpu特别高的线程编号,假设是123
5、执行jstack 123456对当前的进程做 jmap -dump,输出所有的线程信息
6 将第4步得到的线程编号11354转成16进制是0x7b
7 根据第6步得到的0x7b在第5步的线程信息里面去找对应线程内容
8 解读线程信息,定位具体代码位置

定位到cpu过高是IO读写太高 ,接下来就是找开发人员确认这段代码是否可以优化


5.4 Java OOM问题如何排查????

1.查看java 进程/线程对系统的占用情况,如 top -pid
2.jstack pid > file.log 通过jstack 把该进程的所有线程堆栈打印到file.log中
3.jmap -heap 进程/线程号  显示堆内存信息
4.jmap -dump 生成堆内存转储快照
5.加载对比 堆文件,发现 对象增多,初步定位到问题

六、Java


在我非常擅长的java这一块,只问了一个volitize关键字

我说,是一个关键字,只能作用在变量上,保证可见性,防止指令重排,不保证原子性

面试官反问:除了可见性,还能保证什么????


七、反问


我说我自己今天表现不是很好,问问面试官对我有什么地方改进?

面试官:说对我期望特别高,看到我简历说我会的技术栈很全,所以问我的时候并没有刁难我,不要为了面试而面试,而是选择有思考的让我去考虑问题。

最后感谢了面试官,因为真的收获很大,也知道了在学习时候如何如避免形成刻板思路,多思考!!!

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
缓存 算法 编译器
【C/C++ 泡沫精选面试题01】提高c++性能,你用过哪些方式去提升?
【C/C++ 泡沫精选面试题01】提高c++性能,你用过哪些方式去提升?
102 1
|
6月前
|
运维 前端开发 大数据
大数据必知必会系列——面试官一问就懵:你们做过的项目技术是如何选型的?[新星计划]
大数据必知必会系列——面试官一问就懵:你们做过的项目技术是如何选型的?[新星计划]
74 0
|
6月前
|
缓存 算法 Java
堪称神级的阿里巴巴“高并发”教程《基础+实战+源码+面试+架构》
作为一个普普通通的程序员,如何才能提升自己的能力,在职场上拥有一技之长,这也成为普通的你我,迫切的需求。
|
消息中间件 分布式计算 Kubernetes
爆款阿里P5到P7晋升之路,九大源码文档助我超神果然努力幸运并存
前言 相信有许多的程序员,工作了这么多年;但是依然不知道自己掌握的技术栈+项目,究竟达到了阿里的什么职级,还有薪资水平是什么样的;
|
设计模式 缓存 Java
吃透阿里2023版Java性能优化小册后,我让公司系统性能提升了200%
性能优化可以说是很多一线大厂对其公司内高级开发的基本要求(其中以Java岗最为显著)。其原因有两个:一是提高系统的性能,二是为公司节省资源。两者都能做到,那你就不可谓不是普通程序员眼中的“调优大神了”。 那么如何成为一名“调优大神”呢?
|
消息中间件 安全 Java
全网首发!消息中间件神仙笔记,涵盖阿里十年技术精髓
消息中间件是分布式系统中的重要组件,在实际工作中常用消息中间件进行系统间数据交换,从而解决应用解耦、异步消息、流量削峰等问题,实现高性能、高可用、可伸缩和最终一致性架构。
冰河与你聊聊大厂更加看重哪些能力?(建议收藏)
很多小伙伴问我是如何同时拿到 阿里、字节跳动、腾讯、京东、和美团百万年薪Offer的。今天我们就来简单的聊聊除了技术外,大厂还会看重哪些技能,从本质上说,除了技术,互联网大厂更看重这些基础能力!
169 0
冰河与你聊聊大厂更加看重哪些能力?(建议收藏)
|
存储 新零售 云安全
完美日记:一文详解新零售电商定制化安全法则
阿里云作为完美日记选择的安全合作伙伴,从原生数据、场景防护策略到业务风控,为其提供定制化整体安全方案。
1658 0
完美日记:一文详解新零售电商定制化安全法则
|
移动开发 算法 SEO
|
SQL 缓存 NoSQL
“国货之光” 完美日记的微服务实践和优化思路
今年双11,完美日记仅用28分钟就超过了2018年双11全天的销售额,成为第一个登上天猫双11彩妆榜首的国货品牌。他们是如何在 4 个月内筹建、上线电商平台的呢?本文将为您分享他们在实践微服务过程遇到的难点和优化思路。
2128 0
“国货之光” 完美日记的微服务实践和优化思路