自我介绍
面试官您好,我叫XXX,是XXX大学计算机科学与技术专业25届的研究生。在校期间我学习了计算机网络、数据结构、数据库、Java等课程,自学了Java相关技术。我有三段主要的项目经历,第一个项目是实验室的科研项目,采用三维视觉的方法无接触的测量动物体尺,我主要负责数据处理和算法实现,项目结束后以第一作者身份发表了2篇SCI论文。第二个项目是针对植物叶片病害早期诊断问题,我带领团队提出了一种基于语义分割的病害诊断模型,我本人主要负责算法实现、统筹项目进度,利用课余时间自己搭建了一个病害诊断系统,让我对Java工程有了一定的了解,项目结束后以第一作者身份发表了1篇SCI论文。第三个项目是助农直播平台的开发,是实验室近期申请的项目,项目目前还没有开始,出于学习和实践的目的我进行了用户中台开发,让我对mysql、redis产生了更深的理解。
此外,我有较好的团队合作能力、较强的问题分析解决能力以及抗压能力,我以负责人的身份带领团队参加了中国研究生数学建模竞赛和中国机器人及人工智能大赛,均获得了国家级二等奖。这些项目和竞赛锻炼了我的团队合作能力和解决问题的能力。
以上是我的自我介绍,谢谢非常感谢您能给我这次面试机会。(key:学习能力较强,能吃苦,抗压,合作能力强)
“翠绿守护”植物叶片病害诊断系统
项目介绍:
针对人工进行叶片病害种类和病害程度诊断费时费力的问题,提出了一种基于语义分割的病害诊断模型。在这个项目中我是项目负责人,负责算法实现、统筹项目进度等。在项目进行时,发现特征提取过程中的长距离特征丢失,模型仅学习到部分区域特征,导致病害识别准确率较低。提出了一种斜纹池化算法,修改池化层使其可以提取多角度长距离的特征,病害识别准确率从90%提升到99%。最后以第一作者身份发表一篇二区SCI论文。
当时方法大多采用对图像分类的方式进行病害诊断,但这种方法难以准确诊断病害程度,对图片的整体分类容易忽视小面积病斑带来的相近病害程度混淆。因此,我们采用对图像中每个像素点进行分类的方法,将所有的病斑区域分割出来,计算病斑区域占叶片面积的百分比,根据叶片病害诊断标准中对于病害程度的定义进行诊断。为了提升病害诊断的准确率,提出了一种斜纹池化算法。池化是深度学习中一个常见的操作,是对于卷积提取到的图像特征进行特征选择,通常池化层是一个远小于图像大小的矩形滑动窗口。但对于叶片中的病害来说,形状和分布通常是不均匀的,所以提出长距离的斜纹池化,提取远距离的特征,提高病害诊断的准确率。
数据传输过程(架构)
当用户上传一张图片时,服务器首先(protobuf)对图片进行编码处理,提升数据传输效率。由于病害识别模型识别速度较慢,所以将编码后的数据被发布到消息队列中,实现解耦、异步和负载均衡的效果。随后,消费者消费新消息,作为gRPC客户端,将请求发送给gRPC服务端,调用叶片病害识别诊断模型进行诊断,获取诊断结果。gRPC客户端接收到这些结果后,将它们存储在Redis缓存中。最后从Redis中获取查询结果返回给用户。
如何设计Kafka的消息队列?如何实现负载均衡和消息分区的?
创建一个专门用于图像上传的Kafka主题,该主题接收来自客户端上传的图像数据。
客户端作为生产者,将图像数据发布到图像上传主题。每个上传的图像都被封装成一个消息,包含图像数据及其元数据。
服务端的gRPC订阅图像上传主题,消费并将上传的图像发送到服务器。
Kafka自身提供负载均衡的能力,特别是在消费者群组中。通过在服务端部署多个图像处理消费者实例,并将它们归入同一个消费者群组,Kafka能够自动平衡每个消费者的负载,确保处理任务均匀分配。
消费者可以订阅一个或多个分区。在有多个消费者实例的情况下,Kafka会确保每个分区只被一个消费者消费,进一步实现负载均衡。
为什么使用gRPC?
由于项目涉及到大量的图像数据传输,并且需要跨语言调用,需要一种高效的通信方式来减少延迟,提高处理速度。
常见的rpc:
gRPC(谷歌):HTTP2协议、跨语言调用、ProtoBuf序列化、需要手动实现客户端寻址
Dubbo(阿里):底层采用Java、支持多种协议和序列化手段、扩展性强、服务治理手段丰富(负载均衡、流量监控等)
bRPC(百度):C++实现,支持多种协议、ProtoBuf序列化、性能强悍
Thrif(facebook):跨语言调用、支持多种协议和序列化手段
项目中可能需要支持多种编程语言(如Python用于机器学习模型,Java用于后端服务),因此需要一种能够无缝集成多种语言的通信方案。
gRPC使用Protocol Buffers作为接口定义语言(IDL),它是一种轻量级的、高性能的二进制序列化工具,比如JSON这类文本格式更高效,尤其适合于传输大量图像数据。
grpc底层是http2,http2底层是tcp,tcp底层是数据链路层
Docker部署过程?有什么困难?
对于系统中的每个组件(如Python机器学习模型服务、Java Spring Boot后端服务等),编写一个Dockerfile
,该文件包含了构建容器镜像所需的所有指令,包括基础镜像、依赖安装、环境变量设置和启动命令。
使用docker build
命令根据每个Dockerfile
构建容器镜像。每个镜像应该包含运行一个特定服务所需的代码和依赖。
困难:单个服务消耗过多资源。解决方法:为每个服务设置资源限制。
模型性能调优方法?提高准确度的技巧?
数据预处理和数据增强,骨干网络选择,使用预训练模型,批量归一化和正则化,学习率调整策略,梯度裁剪防止梯度爆炸,早停,模型蒸馏
Spring Boot在项目中扮演的角色?它是如何与其他组件(如Kafka、gRPC)集成的?
在这个项目中,Spring Boot主要扮演着构建和运行后端服务的角色,负责管理和协调各种服务之间的交互,以及与前端和机器学习模型的通信。
Spring Boot的角色
- API网关:作为前端和其他微服务(如机器学习模型服务)之间的中介,处理客户端请求,并将这些请求转发到相应的服务。
- 服务协调者:管理各种服务之间的通信,包括请求处理、数据转发和结果聚合。
- 配置中心:通过统一的配置管理,简化服务的配置和环境适配,提高开发和部署的效率。
- 日志和监控:集成各种日志和监控工具,为服务的运行状况和性能提供实时监控。
与Kafka的集成
Spring Boot可以通过Spring for Apache Kafka项目轻松集成Kafka。这主要涉及以下几个方面:
- 配置Kafka生产者和消费者:在
application.properties
或application.yml
文件中配置Kafka生产者和消费者的属性,如服务器地址、序列化器、消费者组ID等。 - 发送消息:使用
KafkaTemplate
发送消息到指定的Kafka主题。 - 监听主题并消费消息:通过
@KafkaListener
注解方法,自动监听指定的Kafka主题,并处理接收到的消息。
与gRPC的集成
Spring Boot与gRPC的集成通常通过使用grpc-spring-boot-starter这样的库来实现,它提供了gRPC服务器和客户端的自动配置支持:
- 定义gRPC服务:使用Protocol Buffers定义gRPC服务接口和消息类型。
- 实现gRPC服务端:在Spring Boot应用中实现定义的gRPC服务,并使用
@GrpcService
注解标记该服务。 - 配置gRPC服务器:在
application.properties
或application.yml
中配置gRPC服务器的相关属性,如端口号。 - 创建gRPC客户端:通过注入的方式创建gRPC客户端实例,以便与其他gRPC服务进行通信。
课题是怎么完成的?
这个课题我是项目复杂人,除了算法改进实现和系统搭建等任务外,还需要负责组内成员分工调配。
实验中遇到的困难问题:算法最初通过代码实现后时间复杂度很高,通过查阅资料,了解到python中的cuda并行编程进行解决。
团队合作中的问题:需要考虑每个人的性格和擅长的地方,分配尽可能符合的工作。比如组内一个同学比较有耐心,静得下心,数据标注的工作又比较枯燥,就分配给这个同学。
冲突:有,实验观点不一致。解决方法:查询相关资料,列出详细的实验设计,开会一起分析,向老师请教。
压力
有没有面对非常大的压力?有,在截稿日期之前需要做完实验、写完论文。每天会加班到很晚。
怎么解决?跑步,劳逸结合。成就感驱动
主要难点(亮点)
主要难点(亮点)是对于算法的改进部分。开始直接使用语义分割方法诊断准确率比较低。将分割的实验结果进行了可视化,观察病斑的特点,对每一类病害图像进行分析,又查阅了大量的论文资料,发现问题可能是特征提取过程中的长距离特征丢失,导致模型仅学习到部分区域特征,这也与可视化的结果相符。
之后根据对模型结构的分析,对其中的池化层进行了一个改进。将其改为可以提取多角度长距离的特征,可以适应各种病斑的形状。
在这段时间为了能尽快提出理论可行的方法,不耽误项目进度,每天都会加班翻阅很多相关的论文,并且对论文里的一些方法进行实践。
用户并发上传图片如何处理?识别模型速度慢(举例子)加入Kafka队列控制流量。
跨语言,如何使用Java调用python程序?grpc
识别速度慢怎么解决?1.模型算法优化,2. 模型需要GPU,所以部署在GPU性能更好的机器,使用gRPC远程调用
改进的算法时间复杂度高,采用cuda并行解决。
不足及改进点
对于算法上的不足,目前只能对单张叶片进行病害诊断,后续可以采用实例分割的方法对一张图片中的每个叶片进行检测,可以针对小目标检测进行算法改进。
对于团队成员选择上的改进,会去选择主观意愿更强烈,愿意一起坚持做下去的同学,而不是尽可能选择能力强的同学。因为愿意坚持的同学,在经过学习以后也能完成任务,但是能力强的同学不一定会认真对待任务。
并且在带领团队的时候,需要尽可能的照顾到每个人的情绪,及时沟通。有一段时间一个同学在忙他自己的事情,可能是我们沟通还是不够,我没有察到这个问题,仍旧给他布置了一些任务,导致他后来对我也有一些不满。如果我们能再多沟通一些,可能结果会更好一点。
目前的用户上传服务在上传图片以后,会一直对redis缓存进行访问,直到取到识别结果。连续查询redis会占用服务器资源,并且用户上传完图片到点击查询结果是需要一段时间的,降低用户对等待结果的感知。改为异步进行,上传服务只进行上传,上传后不再去进行结果查询,释放服务器资源,用于处理其他任务。当用户点击查询结果,发起结果查询服务,从redis中获取查询结果。
项目的收获
通过这个项目锻炼了我解决问题的能力,遇到问题后先进行分析和思考,然后再去网上寻找相关内容,实在解决不了的问题会总结问题和我的思考,然后向其他人请教。再就是锻炼了我的团队合作能力,因为我是负责人,需要考虑团队成员的优缺点进行不同任务的分配,调解成员间的矛盾。
项目过程中如何合作?
我们会定期开会讨论进展,讨论遇到的问题和下一步要做什么。沟通上一般没有太大问题,但是会有人不能按时完成任务,导致项目推进缓慢。
“印象西农”助农直播平台
项目介绍
补充流程图
创建一个包含娱乐、购物和社交的农产品直播平台,助力传统农业的现代化转型。是实验室近期正在申请的一个项目,目前还没有正式开始开发。因为我科研任务完成的比较早,出于学习和实践的目的,进行了用户中台的实现,但是因为业务具体需求还不明确,实现的用户中台目前只有简单的用户注册、登录查询等功能,可能存在一些不合理的地方。
在设计的时候假设有一亿左右的用户量,设计了MySQL的主从架构实现读写分离,并且实现了分表。后来使用redis进一步缓解数据库读的压力。引入redis后出现缓存不一致的问题,使用消息队列实现延迟双删解决这个问题。最后为了保证在分表情况下userid的唯一,设计了一种ID生成器,支持ID的连续生成和非连续生成。
后续开发
企业中怎么处理因业务变动而带来的表结构改变?
你的用户中台比用户管理多了什么?
秒杀:
高性能:
- 热点数据:(热点检测:京东零售的hotkey)
- 静态热点:提前预热,CDN
- 动态热点
- 热点数据:(热点检测:京东零售的hotkey)
高可用:
- Redis 哨兵,集群
限流
- 接口限流:可以直接用 Redis 来做 (基于 Lua 脚本)
- 用户限流:
- 问题/验证码:正确性校验/提交时间限制不能过短
- 提前预约
- 消息队列流量削峰
库存问题:通过Redis对库存进行原子操作
- 下单就减库存 即使不付款
- 付款再减库存
引入分布式缓存Redis加速数据检索过程
1 |
|
- batchQueryUserInfo
- 数据库查询
- 将未命中缓存的用户ID分组,分组依据是用户ID对100取余的结果。这与数据分片策略一致,旨在优化数据库查询。
- 使用 parallelStream 并行查询每个分组的用户信息,查询结果被添加到线程安全的 CopyOnWriteArrayList 中。
- 更新缓存:
- 如果从数据库查询到用户信息,构建一个 saveCacheMap,键是用户信息的缓存键,值是用户信息对象。
- 使用 multiSet 方法将查询结果批量写入缓存。
- 管道为了减少IO的开销,使用 executePipelined 方法设置每个缓存项的过期时间,这里生成随机的过期时间,以避免缓存同时失效引起的缓存雪崩问题。
- 数据库查询
为什么要开发分布式ID生成器?
因为进行了分表,MySQL主键自增可能会出现重复id,可以通过新建一个表专门进行id自增,但是每次获取 ID 都要访问一次数据库(增加了对数据库的压力,获取速度也慢),并且会出现安全问题(早上,晚上)。现有的uuid长度过长并且是无序的,存储消耗空间大(32 个字符串,128 位),需要解决重复 ID 问题(当机器时间不对的情况下,可能导致会产生重复 ID)。因此自己实现了一个ID生成器。
分布式ID生成器通过本地缓存+MySQL实现,在MySQL中建立一张表,包括起始id,当前id,id段的大小,id的version等。ID生成器服务访问数据库获得当前id,根据id段的大小申请一段id,并且将id的version加1。比如,当前的id是1000,id段的大小为500,id生成器就申请到了1000-1500这段id的使用权。但是同一时间可能会出现多个id生成器同时申请id,为了防止申请到同样的id段,使用乐观锁的版本控制方法,设置了id的version,每次申请前先查询一次现在的version号,申请的时候判断之前查询的version与数据库里的version是否相同,如果相同就代表这段id没有被申请,返回这段id,然后另version+1。为了防止字段用完后申请字段的时间内出现长时间等待,当字段使用75%时就开始申请。
非连续id是在申请到id段后,对这一段id使用collection.shuffle进行打乱,保证整体id递增但局部是乱序。
MySQL
"id" "next_threshold" "init_num" "current_start" "step" "is_seq" "id_prefix" "version" "1" "2000" "1000" "1500" "500" "1" "user_id" "1"
初始化 (afterPropertiesSet
方法):
- 调用
idGenerateMapper.selectAll()
从数据库中查询所有的ID生成器配置信息 (IdGeneratePO
对象列表)。 - 遍历这些
IdGeneratePO
对象,并为每个对象调用tryUpdateMySQLRecord
方法来尝试更新MySQL记录,这实质上是为了抢占新的ID段。这个操作将为每种ID生成器预分配一段ID范围,并将其加载到内存中以供后续快速访问。 - 对于每个ID生成器,还会在
semaphoreMap
中创建并存储一个新的Semaphore
对象,以控制对该ID生成器并发更新的同步访问。
**非连续ID生成 (getUnSeqId 方法)**:
- 首先检查传入的ID是否为
null
,如果是,则记录错误并返回null
。 - 从
UnSeqIdBOMap
中根据ID获取对应的UnSeqIdBO
对象。如果对象不存在,则记录错误并返回null
。 - 从
LocalUnSeqIdBO
的ID队列 (idQueue
) 中取出一个ID并返回。如果队列为空,则记录错误并返回null
。 - 如果返回的ID不为
null
,则调用refreshLocalUnSeqId
方法来检查是否需要从数据库中刷新本地的ID队列。
当服务启动后,IdGenerateServiceImpl
类会预加载D生成器的ID段到内存,并为每个ID生成器准备一个信号量以同步更新操作。对于非连续ID生成的并发请求,它们会安全地从各自的ID队列中取ID,且当ID使用达到一定阈值时,会异步地从数据库刷新ID队列,保证ID生成的连续性和高效性。
单纯JDBC和shardingJDBC性能的差异?
Dubbo负载均衡策略
- 随机(Random): 默认策略,按权重设置随机概率。
- 轮询(Round Robin): 按公约后的权重设置轮询比率,逐一调用。
- 最少活跃调用数(Least Active): 对相同服务的活跃数最小的提供者进行调用(活跃数指调用前后计数差)。
- 一致性 Hash(Consistent Hash): 相同参数的请求总是发到同一提供者。
主要难点TODO
缓存一致性
分布式ID乐观锁
排查bug
多接口登录(不足及改进点)
用户登录优化-引入手机号登陆
id用户难以记住,增加手机号注册登录。每个手机号对应一个用户,手机号为必填项。
流程:
- 输入手机号,然后发送到服务端。服务端生成随机验证码,将手机号和验证码绑定到
Redis
中,并设置一定的过期时间(过期时间一般是5分钟,这就是我们一般手机验证码的有效期),最后将验证码通过短信发送给用户。 - 用户接收到验证码后,在界面只需填写收到的验证码,提交到服务端。服务端收到后,先判断在
Redis
里面这个手机号对应的验证码是否一致,失败就返回错误码,成功就直接登录。如果是老用户,直接拉取用户信息;如果是新用户,则提示他可以完善用户信息(不强制)。 - 用户通过
手机号+验证码
登录后,也可选择设置密码,然后就可以通过手机号+密码
的方式登录,即:密码是非必填项。
引入第三方账户登录
用户基础信息表:
id | nickname | avatar | more |
---|---|---|---|
用户id | 昵称 | 头像 | 其他信息 |
用户授权信息表:
id | user_id | identity_type | identifier | credential |
---|---|---|---|---|
主键id | 用户id | 登录类型(手机号/邮箱) 或第三方应用名称 (微信/微博等) | 手机号/邮箱/第三方的唯一标识 | 密码凭证 (自建账号的保存密码, 第三方的保存 token) |
用户信息表不保存任何密码, 不保存任何登录信息(如用户名, 手机号, 邮箱), 只留有昵称、头像等基础信息; 所有和授权相关,都放在用户信息授权表, 用户信息表和用户授权表是一对多的关系 。
手机号+验证码
沿用之前的方案。
邮箱/手机号+密码
:
用户填写 邮箱/手机号+密码
; 请求登录的时候, 先判断类型, 如手机号登录为例:
使用 type='phone'
结合 identifier='手机号'
查找, 如有, 取出并判断 password_hash
(密码)是否和该条目的 credential
相符, 相符则通过验证, 随后通过 user_id
获取用户信息;
- 第三方登录, 如微信登录:
查询 type='weixin'
结合 identifier='微信 openId'
, 如果有记录, 则直接登录成功, 并更新 token
; 假设与微信服务器通信不被劫持的情况下无需判断凭证问题。
优缺点
优点:
- 登录类型无限扩展, 新增登录类型的开发成本显著降低;
- 原来条件下, 应用需要验证手机号是否已验证和邮箱是否已验证, 需要相对应多一个字段如
phone_verified
和email_verified
, 如今只要在用户授权信息表
表中增加一个统一的verified
字段, 每种登录方式都可以直观看到是否已验证情况; - 在
用户授权信息表
添加相应的时间和IP
地址, 就可以更加完整地跟踪用户的使用习惯, 比如:已经不使用微博登录两年多, 已经绑定微信 300天; - 如果你说邮箱和手机号就是用户信息的组成部分, users 表尽管拓展, users 表里依然有email , phone , 但他们仅仅作为“展示用途”,和昵称,头像或者性别这些属性没有本质区别;
- 可按需绑定任意数量的同类型登录方式, 即一个用户可以绑定多个微信, 可以有多个邮箱, 可以有多个手机号。当然你也可以限制一种登录方式只有一条记录;
缺点 :
- 用户同时存在邮箱、用户名、手机号等多种站内登录方式时, 改密码时必须一起改, 否则就变成了
邮箱+新密码
,手机号+旧密码
都可以登录, 肯定是很诡异的情况; - 代码量增加了, 有些情况下逻辑判断增加了, 难度增大了; 举个例子, 无论用户是否已登录, 无论用户是否已注册过, 都是点击同一链接前往微博第三方授权后返回, 可能出现几种情况:
- 该微博在本站未注册过, 很好, 直接给他注册关联并登录;
- 该微博已经在本站存在, 当前用户未登录, 直接登录成功;
- 该微博未在本站注册, 但当前用户已经登录并关联的是另一个微博帐号, 作何处理取决于是否允许绑定多个微博帐号;
- 该微博未在本站注册过, 当前用户已登录, 尝试进行绑定操作;
- 该微博已经注册, 用户又已使用该帐号登录, 为何他重复绑定自己;
- 该微博已经在本站存在, 但当前用户已经登录并关联的是另一个微博帐号, 作何处理?
用户标签
记录用户在直播平台的相关特征信息,比如长期活跃、消费能力强、每日任务完成等(json存放MongoDB、mysql),采用mysql实现,设计一张标签表(每个标签一个字段,需要不停变动表结构,耗费空间->预留三个标签字段,设计为bigint类型,用十进制对应的二进制01表示标签,每个字段能够存储多个标签。假设有一个用户的标签是1,对应的二进制是00001,现在需要给这个用户再打上一个值为16的标签,标签转为二进制就是10000,对用户现有标签和需要打上的标签做一个或运算,变为10001。假设要取消刚才打上的值为16的标签,先对16进行取反操作,然后再将现有标签和取反后的标签做一个与运算
监控到某个api某个时刻请求响应时间异常,如何解决和分析?
检查服务器的日志,收集异常发生时的相关信息(具体时间、请求内容、响应时间、错误消息等),判断异常是偶发还是持续发生(有可能是网络波动或者服务器短暂负载高峰,检查服务器网络是否异常或拥堵),具体判断异常时间是否涉及数据库、外部API等。检查是否因为相关代码冗余导致异常。
如何提高QPS?
异步处理,适用于无需对上游返回数据场景。
无锁设计,避免或者使用互斥资源,所以基于数据版本的乐观锁 有效的减少了互斥资源的范围
batch处理,批量查询、批量commit,基本上操作慢速设备或者不能并行化的对象或者资源时,使用batch 永远是最好的手段。
副本设计,使用cache、静态化等手段,其核心思想在于 提前将结果准备好,实现的难点数据的更新。
服务器宕机数据丢失怎么办?
对MySQL进行全量备份和增量备份,对redis使用RDB和AOF持久化。
在进行数据库更新操作时,利用消息队列(如Kafka、RabbitMQ)记录操作日志,如果发生宕机,可以从消息队列中读取未完成的操作日志来恢复数据。
使用云服务提供商(如AWS、Azure、Google Cloud等)提供的数据库服务。
敏感字段(密码)怎么保证一致?
敏感字段不使用redis。
数据库和缓存数据强一致场景:更新 db 的时候同样更新 cache,不过我们需要加一个锁/分布式锁来保证更新 cache 的时候不存在线程安全问题。
消息队列挂了
针对生产阶段:
在生产者端设置开启 confirm 模式之后,你每次写的消息都会分配一个唯一的 id,然后如果写入了 MQ 中,MQ 会给你回传一个 ack 消息,告诉你说这个消息 ok 了。如果 MQ 没能处理这个消息,会回调你的一个 nack 接口,告诉你这个消息接收失败,你可以重试。而且可以结合这个机制自己在内存里维护每个消息 id 的状态,如果超过一定时间还没接收到这个消息的回调,那么你可以重发。
confirm
机制是异步的,你发送个消息之后就可以发送下一个消息,然后消息 被RabbitMQ 接收了之后会异步回调你的一个接口,通知你这个消息接收到了。所以一般在生产者这块避免数据丢失,都是采用 confirm 机制的。
针对存储阶段:
开启 MQ 的持久化,就是消息写入之后会持久化到磁盘,MQ 自己挂了,恢复之后会自动读取之前存储的数据,一般数据不会丢。除非极其罕见的是,MQ 还没持久化,自己就挂了,可能导致少量数据丢失,但是这个概率较小。
针对消费阶段:
消费的时候,刚消费到,还没处理,结果消费进程挂了。导致MQ 认为已经消费了数据。每次数据处理完后手动 ack。这样的话,如果还没处理完,不就没有 ack
了?那 MQ 就认为你还没处理完,这个时候MQ 会把这个消费分配给别的 consumer 去处理,消息是不会丢的。
但是此时可能出现消息重复消费的问题,假如消费者刚消费完,正要准备给MQ发送ack,但是此时消费者挂掉了,消息队列没有收到ack,认为消息没有被成功消费,将这个消息分配给别的消费者进行消费,出现了消息的重复消费。对于延迟双删任务来说,出现了消息的重复消费也是可以容忍的,如果要解决重复消费问题,我觉的可以用这种方法。
- 状态判断法:可以给每一个消息携带一个全局唯一的id,消费者消费数据后把消费数据记录在 redis 中,下次消费时先到 redis 中查看是否存在该消息,存在则表示消息已经消费过,直接丢弃消息。
- 业务判断法:通常数据消费后都需要插入到数据库中,使用数据库的唯一性约束防止重复消费。每次消费直接尝试插入数据,如果提示唯一性字段重复,则直接丢失消息。一般都是通过这个业务判断的方法就可以简单高效地避免消息的重复处理了。
如何保持缓存一致性?
先写mysql,再删redis(假设现在redis中不存在缓存,A线程更新时,B线程从数据库读取到旧数据,此时A线程更新完成并且去删除redis,发现redis中没有缓存,A线程结束。B线程此时将旧数据写入到缓存中。所以需要二次删除。
先更新MySQL,删除redis,延迟二次删除redis(先更新是因为防止更新失败直接删除了redis)
虽然可以直接阻塞1秒后进行删除,但是需要阻塞等待,而且阻塞时如果出现服务挂掉,可能导致删除失败,redis中仍旧是旧数据。消息队列可以将消息持久化,在一定程度上保证删除成功。
MySQL主从不一致
可能不同步的情况:
网络延迟、主从两台机器的负载或性能不一样、同步参数设置问题(mysql异常宕机情况下,如果未设置sync_binlog=1或者innodb_flush_log_at_trx_commit=1很有可能出现binlog或者relaylog文件出现损坏,导致主从不一致。)、版本不一致等等
如果不能容忍网络导致的短期不一致,可以强制走主库。
解决方法:
忽略错误后,继续同步(在业务不保证数据强一致性的情况下)
重做主从,完全同步:
1.先进入主库,进行锁表,防止数据写入
2.进行数据备份
1.停止从库的状态
2.清除从节点配置信息(仅清理master.info 和 relay-log.info 文件)
3.从库执行mysql命令,导入数据备份
4.设置从库同步
ShardingJDBC如何实现读写分离
配置读写分离:
主从数据库的名字、主从数据库的连接信息、读写分离配置、最终的数据源名称、库数据源名称、从库数据源名称列表
高并发情况下ID生成器生成的段内id怎么保证不会被重复分发?
数据库中的乐观锁保证id段不会出现冲突
增加消息队列保证给每个用户时不会冲突
MySQL如何实现主从复制和读写分离?
建立主从复制过程:
Master(主数据库)将用户对数据库更新的操作以二进制格式保存到BinaryLog日志文件中。
Slave(从数据库)上面的IO进程连接上Master, 并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容。
Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置。
Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master “我需要从某个bin- log的哪个位置开始往后的日志内容,请发给我”。
Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay- log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
管理系统和用户中台的区别
用户中台,通常在企业的信息技术架构中使用,是一种以用户为中心的服务和技术平台,旨在通过集成各种用户数据和服务,提供统一的用户视图和体验。用户中台的核心在于对用户信息的集中管理和应用,通过这种方式可以提高服务的个性化和效率,增强用户满意度和忠诚度。
用户中台:
- 目标:以用户为中心,旨在为用户提供一致、个性化的体验,并在企业内部不同的业务线、产品和服务之间共享用户信息。
- 功能:包括用户身份验证、权限管理、用户数据分析、个性化推荐、客户关系管理等。用户中台聚焦于提高用户满意度、增强用户参与度和优化用户体验。
- 数据集成:用户中台通常需要集成来自企业内外的多源用户数据,包括用户行为数据、偏好设置、交易历史等,以构建全面的用户画像。
管理系统:
- 目标:侧重于企业内部的运营管理,如资源规划、财务管理、人力资源管理等,以提高企业的运营效率和管理效果。
- 功能:包括任务分配、进度跟踪、财务报告、资源调配等。管理系统更多地聚焦于企业内部流程和资源的优化管理。
- 数据使用:管理系统主要处理企业内部数据,如员工信息、财务数据、生产和库存数据等,重点是优化内部流程和提高效率。
ShardingJDBC执行过程
简历技术相关面试题
Java
集合
Java集合常见面试题总结(上) | JavaGuide(LIst、Set、Queue)
Java集合常见面试题总结(下) | JavaGuide(Map、Collections)
注解
Java基础常见面试题总结(下) | JavaGuide(何为注解?注解的解析方法?)
反射
Java基础常见面试题总结(下) | JavaGuide(何为反射?反射的优缺点?应用场景?)
JVM
Java内存区域详解(重点) | JavaGuide(内存区域)
JVM垃圾回收详解(重点) | JavaGuide(垃圾回收)
类文件结构详解 | JavaGuide(类文件结构)
类加载过程详解 | JavaGuide(类加载过程)
类加载器详解(重点) | JavaGuide(类加载器)
框架相关
MyBatis常见面试题总结 | JavaGuide(mybatis)
Spring常见面试题总结 | JavaGuide(Spring)
SpringBoot 常见面试题总结 (yuque.com)(springboot)
Docker
终于有人把 Docker 讲清楚了,万字详解! - 知乎 (zhihu.com)
什么是Docker?
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类iphone的app),并且容器开销极其低。
Docker的作用
- 发布服务不用担心服务器的运行环境,所有的服务器都是自动分配docker,自动部署,自动安装,自动运行
- 再不用担心其他服务引擎的磁盘问题,cpu问题,系统问题了
- 资源利用更出色
- 自动迁移,可以制作镜像,迁移使用自定义的镜像即可迁移,不会出现什么问题
- 管理更加方便了
Docker的功能?
- 资源限制:可以对任务使用的资源总额进行限制
- 优先级分配:通过分配的cpu时间片数量以及磁盘IO带宽大小,实际上相当于控制了任务运行优先级
- 资源统计:可以统计系统的资源使用量,如cpu时长,内存用量等
- 任务控制:cgroup可以对任务执行挂起、恢复等操作
注册中心(nacos)
什么是注册中心?
注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。
注册中心的作用?
- 服务注册,就是将提供某个服务的模块信息(通常是这个服务的ip和端口)注册到1个公共的组件上去(比如: zookeeper\consul)。
- 服务发现,就是新注册的这个服务模块能够及时的被其他调用者发现。不管是服务新增和服务删减都能实现自动发现。
Kafka和RocketMQ对比
吞吐量
Kafka的吞吐量比rocketmq更高,因为Kafka的producer端将多个小消息合并,批量进行发送。Kafka采用异步发送的机制,当发送一条消息时,消息并没有发送到broker而是缓存起来,然后直接向业务返回成功,当缓存的消息达到一定数量时再批量发送。这种方法减少了网络io,从而提高了消息发送的性能,但是如果消息发送者宕机,会导致消息丢失,业务出错,所以理论上kafka利用此机制提高了io性能却降低了可靠性。
RocketMQ通常使用的Java语言,缓存过多消息会导致频繁GC。
存储
Kafka的一个topic后面对应了多个partition(如果topic只有一份的话,那么所有的实例都会来消费消息,并且都是抢占我们一个topic,这不可避免引入了多实例竞争,以及他们之间怎么协调,一堆问题需要关注解决,现在我把topic分成了很多份,每一份只给一个实例,那么就不会引入各实例之间的竞争问题了,简化了mq的问题)。一个partition对应一个文件,每次消息来都是顺序写这个文件(并且是定时刷盘,而不是每次写都刷盘,所以kafka的写非常高效)。
rocketmq借鉴于kafka,将partition变为了consumeQueue,kafka,里面partition存储的是整个消息,但是现在ConsumeQueue里面是存储消息的存储地址,但是不存储消息了。每个ConsumeQueue存储的是每个消息在commitlog这个文件的地址,消息存在于commitlog中,也就是所有的消息体都写在了一个文件里面,每个ConsumeQueue只是存储这个消息在commitlog中地址。
假设Kafka有1000个partition,一个partition是顺序写一个文件,总体上就是1000个文件的顺序写,就变成了随机写,当partition增加到一定数目后,kafka性能就会下降。而rocketmq是把消息都写到一个CommitLog文件中,所以相当于一个文件的顺序写。
(此处尽量不提)虽然rocketmq会带来1000个consumeQueue,ConsumeQueue只存储了(CommitLog Offet指向commitlog中文件的偏移量 + Size该条消息大小 + Message Tag Hashcode生产消息时指定的 tag 的hash 值,tag是在topic基础上对消息更细粒度的分类),一共20个字节,那么当commitlog定时任务刷盘之后,应该回写的pagecache的比例就会下降很多,那么ConsumeQueue的部分可以不用刷盘,就相当于ConsumeQueue的内容会等待比较长的时间聚合批量写入,而kafka每个partition都是存储的消息体,因为消息体都相对较大,基本在kb之上。当一个partition刷盘的时候,应该回写的pagecache的比例降低的并不多,不能阻止其他partition的刷盘,所以会大量存在多个partition同时刷盘的场景,变成随机写。但是rocketmq消息都会写入一个commitLog,也就是顺序写。
优先级队列
- Kafka:不支持优先级队列
- RocketMQ:支持相对意义上的优先级队列,RocketMQ是通过建立不同的队列,每个队列有不同的优先级,当producer根据message的消息优先级发送到对于的队列。
消费模式
push模式是broker端推送消息到consumer端,实时性高,但是需要进行流量控制以防止consumer端被压垮;pull模式是broker端去broker拉取消息,实时性较推模式差,但是可以根据自身的处理能力而控制拉取的消息量。
- Kafka:kafka是pull模式。
- RocketMQ:Rocketmq消费分为push和pull两种方式,push为被动消费类型,pull为主动消费类型,push方式最终还是会从broker中pull消息。不同于pull的是,push首先要注册消费监听器,当监听器处触发后才开始消费消息,所以被称为“被动”消费。
消息过滤
- Kakfa不支持Broker端的过滤,但是可以通过客户端提供的 ConsumerInterceptor 接口或者 Kafka Stream 的 filter 功能进行消息过滤。
- RocketMQ支持Broker端消息过滤方式
根据Message Tag来过滤,相当于子topic概念
定时消息
- Kafka不支持定时消息
- RabbitMQ、RocketMQ支持定时消息
刷盘策略
- kafka:缺省Kafka是异步刷盘,每3s钟,调用1次fsync。但Kafka支持同步刷盘,也就是说,你可以每写入1条消息,就刷盘1次。
- RocketMQ:RocketMQ支持三种刷盘策略:
线程服务 场景 插入性能
CommitRealTimeService 异步刷盘 && 开启内存字节缓冲区 第一
FLushRealTimeService 异步刷盘 && 关闭内存字节缓冲区 第二
GroupCommitService 同步刷盘 第三
spring如何解决循环依赖?
【Spring框架】一篇文章带你彻底搞懂Spring解决循环依赖的底层原理_为什么重新打一次包就不会循环依赖-CSDN博客
为什么会产生?
假如A、B两个类相互注入,当 AService 创建时,会先对 AService 进行实例化生成一个原始对象,然后在进行属性注入时发现了需要 BService 对应的 Bean,此时就会去为 BService 进行创建,在 BService 实例化后生成一个原始对象后进行属性注入,此时会发现也需要 AService 对应的 Bean。
而这种情况只会在将Bean交给Spring管理的时候才会出现,因为上面的这些属性注入操作都是Spring去做的,如果只是我们自己在Java中创建对象可以不去注入属性,让成员属性为NULL也可以正常执行的,这样也就不会出现循环依赖的问题了。
什么情况下循环依赖可以被处理?
- 出现循环依赖的Bean必须要是单例
如果原型的Bean出现循环依赖,Spring会直接报错,Spring 无法解决 原型作用域 出现的循环依赖问题。因为 Spring 不会缓存 原型 作用域的 Bean,而 Spring 依靠 缓存 来解决循环依赖问题,所以 Spring 无法解决 原型 作用域的 Bean。
- 依赖注入的方式不能全是构造器注入的方式
A中注入B的方式是通过构造器,B中注入A的方式也是通过构造器,这个时候循环依赖是无法被解决,如果项目中有两个这样相互依赖的Bean,在启动时就会报出错误。因为构造器注入发生在实例化阶段,而 Spring 解决循环依赖问题依靠的三级缓存在属性注入阶段,也就是说调用构造函数时还未能放入三级缓存中,所以无法解决构造器注入的循环依赖问题。
Spring如何解决循环依赖问题
Java设计模式
Java 23种设计模式全归纳 | 完结版-腾讯云开发者社区-腾讯云 (tencent.com)
如何排查OOM
为什么会OOM:
- 内存泄漏:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了。因为申请者不用了,而又不能被虚拟机分配给别人用
- 内存溢出:申请的内存超出了 JVM 能提供的内存大小
常见错误:
虚拟机栈溢出,一般是由于程序中存在 死循环或者深度递归调用 造成的。如果栈大小设置过小也会出现溢出,可以通过 -Xss
设置栈的大小
Java 堆内存溢出,溢出的原因一般由于 JVM 堆内存设置不合理或者内存泄漏导致
如果是内存泄漏,可以通过工具(Dump 文件分析,工具:JvisualVM)查看泄漏对象到 GC Roots 的引用链。掌握了泄漏对象的类型信息以及 GC Roots 引用链信息,定位出泄漏代码的位置
如果不存在内存泄漏,就是内存中的对象确实都还必须存活着,那就应该检查虚拟机的堆参数(-Xmx 与 -Xms),查看是否可以将虚拟机的内存调大些
Hash索引和B+tree索引的区别
1、在查询速度上,如果是等值查询,那么Hash索引明显有绝对优势,因为只需要经过一次 Hash 算法即可找到相应的键值,复杂度为O(1);当然了,这个前提是键值都是唯一的。如果键值不是唯一(或存在Hash冲突),就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据,这时候复杂度会变成O(n),降低了Hash索引的查找效率。所以,Hash 索引通常不会用到重复值多的列上,比如列为性别、年龄的情况等(当然B+tree索引也不适合这种离散型低的字段上);
2、Hash 索引是无序的,如果是范围查询检索,这时候 Hash 索引就无法起到作用,即使原先是有序的键值,经过 Hash 算法后,也会变成不连续的了。因此
①、Hash 索引只支持等值比较查询、无法索成范围查询检索,B+tree索引的叶子节点形成有序链表,便于范围查询。
②、Hash 索引无法做 like ‘xxx%’ 这样的部分模糊查询,因为需要对 完整 key 做 Hash 计算,定位bucket。而 B+tree 索引具有最左前缀匹配,可以进行部分模糊查询。
③、Hash索引中存放的是经过Hash计算之后的Hash值,而且Hash值的大小关系并不一定和Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算。B+tree 索引的叶子节点形成有序链表,可用于排序。
3、Hash 索引不支持多列联合索引,对于联合索引来说,Hash 索引在计算 Hash 值的时候是将索引键合并后再一起计算 Hash 值,不会针对每个索引单独计算 Hash 值。因此如果用到联合索引的一个或者几个索引时,联合索引无法被利用;
4、因为存在哈希碰撞问题,在有大量重复键值情况下,哈希索引的效率极低。B+tree 所有查询都要找到叶子节点,性能稳定;
redis解决幂等
下游传递唯一请求编号
① 下游服务生成分布式 ID 作为序列号,然后执行请求调用上游接口,并附带“唯一序列号”与请求的“认证凭据ID”。
② 上游服务进行安全效验,检测下游传递的参数中是否存在“序列号”和“凭据ID”。
③ 上游服务到 Redis 中检测是否存在对应的“序列号”与“认证ID”组成的 Key,如果存在就抛出重复执行的异常信息,然后响应下游对应的错误信息。如果不存在就以该“序列号”和“认证ID”组合作为 Key,以下游关键信息作为 Value,进而存储到 Redis 中,然后正常执行接来来的业务逻辑。
防重Token令牌
针对客户端连续点击或者调用方的超时重试等情况,例如提交订单,此种操作就可以用 Token 的机制实现防止重复提交。简单的说就是调用方在调用接口的时候先向后端请求一个全局 ID(Token),请求的时候携带这个全局 ID 一起请求(Token 最好将其放到 Headers 中),后端需要对这个 Token 作为 Key,用户信息作为 Value 到 Redis 中进行键值内容校验,如果 Key 存在且 Value 匹配就执行删除命令,然后正常执行后面的业务逻辑。如果不存在对应的 Key 或 Value 不匹配就返回重复执行的错误信息,这样来保证幂等操作。
主要流程:
① 服务端提供获取 Token 的接口,该 Token 可以是一个序列号,也可以是一个分布式 ID 或者 UUID 串。
② 客户端调用接口获取 Token,这时候服务端会生成一个 Token 串。
③ 然后将该串存入 Redis 数据库中,以该 Token 作为 Redis 的键(注意设置过期时间)。
④ 将 Token 返回到客户端,客户端拿到后应存到表单隐藏域中。
⑤ 客户端在执行提交表单时,把 Token 存入到 Headers 中,执行业务请求带上该 Headers。
⑥ 服务端接收到请求后从 Headers 中拿到 Token,然后根据 Token 到 Redis 中查找该 key 是否存在。
⑦ 服务端根据 Redis 中是否存该 key 进行判断,如果存在就将该 key 删除,然后正常执行业务逻辑。如果不存在就抛异常,返回重复提交的错误信息。
Java锁
史上最全java中锁的总结! - 知乎 (zhihu.com)
设计模型
Java 23种设计模式全归纳 | 完结版-腾讯云开发者社区-腾讯云 (tencent.com)
对于XX公司的了解
阿里云
目前市场上比较有名的云服务提供商是阿里云、腾讯云、华为云。阿里云的市场份额最高,并且阿里云的创立时间(2009)也是早于腾讯云(2013)。阿里云为大量的企业、个人用户提供服务,拥有国内云服务器最完善的产品生态和多种多样的解决方案提供商。
api管理平台,提供 OpenAPI 的文档、调试工具、SDK 及示例,帮助快速入门 API 开发,提供错误诊断、调用统计、实践场景实例等。
飞天操作系可以统将遍布全球的百万级服务器连成一台超级计算机,以在线公共服务的方式为社会提供计算能力。最底层是遍布全球的几十个数据中心,数百个PoP节点。有两个最核心的服务,一个叫盘古,一个叫伏羲。盘古是存储管理服务,伏羲是资源调度服务,飞天内核之上应用的存储和资源的分配都是由盘古和伏羲管理。还有一个服务,叫做天基,是飞天的自动化运维服务,负责飞天各个子系统的部署、升级、扩容以及故障迁移。核心服务:计算、存储、数据库、网络。
云计算,是用足够的低成本、商业化的模式来解决大计算的问题。以前大家只会想到超级计算机,它的运营成本高,而反应速度还是很慢,当这些大的互联网应用真正发展时,比如淘宝,数亿商家提出的购买需要,实时信息匹配的背后,就是大数据的计算。所以,云计算就是使用分布式的方法,针对海量数据大计算的一种解决方案。如果没有计算能力,我们谈不上大数据的时代,更谈不上海量数据的高效应用
淘天
阿里淘天:甩掉包袱后,要剑指何方?-36氪 (36kr.com)
淘天
淘天是阿里巴巴集团的业务集团,旗下拥有淘宝、天猫、天猫国际、淘宝直播、天猫超市、淘菜菜、淘特、闲鱼、阿里妈妈、1688等业务,提供线上零售、线上批发、二手闲置交易、数字营销等服务
客户运营部
客户运营部在淘天集团扮演着至关重要的角色,对应着阿里巴巴价值观中的”客户第一“。这个部门支持淘宝、天猫等多个业务部门,通过领先的智能化技术手段为这些业务提供专业、高效、优质的服务解决方案。
淘天vs拼多多vs抖音
首先对比淘天最大的竞争对手拼多多和抖音。拼多多的核心优势在于通过最低的价格、最大化的让利于消费者。抖音的优势在于自身的流量大,并且通过短视频、直播等方式可以在产生需求阶段就提前介入,比如直播带货种草,从上游阶段开始分流购物需求。
针对拼多多的低价,淘天上线了百亿补贴、淘工厂等频道来提高性价比;另一方面也发展直播、短视频内容生成,同样在上游阶段开始种草来反击抖音。
淘天的核心优势我觉得在于店铺资产和商品种类丰富。
店铺资产
零售渠道的卖货逻辑可以简单区分为两种,一是以商品本身为核心的商品逻辑,另一种则是侧重店铺的渠道和服务价值的店铺逻辑。
其中,商品逻辑是商品的价格和质量优势,消费者并不特别在意卖家是谁,这种模式下商家和平台主要价值在于快速高效地促成交易,因此商品品类上更适用于标品、日用品,也更契合有较明确购买目标和预算的购物行为。
在店铺逻辑下,店铺或者说渠道的“品质”同样会对消费者的购买决策产生影响。除了最基础的卖货功能外,商家提供的个性化导购、福利、甚至社交情感需求同样对消费者有不小的价值。作为回报,买家或出于习惯或信赖,即便商品价格/质量可能并不是最优的,也会优先在该店铺购买。店铺逻辑比较适合非标商品,适合于“边逛边买”的消费行为。
如何提升?
实现“店号一体”:即把同一个商家控制的淘宝天猫店铺,直播带货的直播账号,以及发布种草图文短视频的账号融合在一起,打通三者间的数据和用户流通,把原先割裂的“短视频种草”、“直播带货”、“店铺货架”融合在一起,让用户能够在同一个店铺/页面内,完成发现需求、比对商品、到付钱购物的完成消费流程。
AI工具助力内容生产:对应着淘天在“逛功能”和直播&短视频上的重视,淘天基于阿里大模型和AICG技术,为商家开发了能智能一键生成商品介绍图、推广文案、甚至短视频的AI工具。有助于商家减少在产生相关内容上所需的时间。
AI不仅利好商家,实际也能利好平台:从商家的角度来看,上述广告、制作、分析工具都是为了能提升商家的经营效率。但换个角度来看,虽然在推广初期和技术成熟前,上述工具可能是免费的。但为商家提效的同时,对平台而言其实也意味着潜在的付费空间。
阿里巴巴文化价值观
使命:让天下没有难做的生意
愿景:追求成为一家活102年的好公司。我们的愿景是让客户相会、工作和生活在阿里巴巴。
价值观:
客户第一,员工第二,股东第三
因为信任,所以简单
唯一不变的是变化
今天最好的表现是明天最低的要求
此时此刻,非我莫属
认真生活,快乐工作
反问
从企业的角度来看,我的项目优缺点是什么?
企业在设计用户中台系统时考虑哪些内容?有哪些难点?
面试表现怎么样?应该往哪方面努力更契合企业的用人标准?实践、深入、技术选型,接口、实现。技术的差别
部门的主要业务是什么?工作中心是什么?
后续流程是什么?多久能出结果?
如果有希望到您所在的部门实习,我应该提前学习哪方面的知识?我希望去了以后能够尽快帮大家分担一些工作。
我看官网上的状态还是简历评估,后续还有哪些流程呢
您对我的简历有什么修改建议吗?
贵公司对于暑期实习生的培养方式是什么样的呢?
其他HR类问题
最让你有成就感的事?
让我有成就感的事有很多,比如我收到保研成功的消息、论文被收录的消息、debug解决了代码中的问题等等,但是我觉得成就是过去发生的,不能一直沉浸在过去的成就中,而是应该向前看,为下一件让我有成就感的事而努力,所以我认为最让我有成就感的事是下一件事。
我觉得最让我有成就感的事并不特指某一件事而是我正在努力想要完成的事。让我有成就感的事有很多,比如我以第一名的成绩保研,论文被收录,前两天完成了人生第一场马拉松等等,但是我觉得不能一直沉浸在过去的成就中,而是应该向前看,为下一件最有成就感的事而努力。
个人优缺点?(自我评价)
优点:坚持,抗压能力强,自驱能力强,具有团队合作意识。
我认为既然选择做一件事,就尽可能地坚持下来,尽自己能力把他做好,在做的过程中肯定会肯定会遇到困难,会有很多压力,如果能将压力化为动力,并且设定多个小目标,坚持到最后,结果也不会太差。而且很多事一个人完成是比较困难的,大家一起合作集思广益,很容易打开思路,更好的完成任务。
比如参加数学建模竞赛的时候,这个比赛需要在3-4天的时间内建立一个数学模型,使用代码实现验证,并且写出一篇论文。中途很多同学因为题难或者时间不够等各种原因弃赛,但是对我来说尽管题很难,我也会尽我最大的努力去思考和查找解决方法,会设定很多个小目标进行自驱。并且我们小组内也会讨论每道题的解决思路,并且分工完成各自擅长的题目。
缺点:有一点内向,在人多的陌生场合讲话会紧张。
这个缺点在我意识到以后我也会有意的改变和克制,原来刚上大学的时候在班里自我介绍都只能说说名字,现在经过准备已经可以在几十人的会议中作报告了。在今后我也会继续锻炼自己,争取让这个缺点消失。
你与其他人不同的点
我觉得我会勇于尝试一些事情,在过程中遇到困难也会尽可能的坚持。比如我之前提到的参加了研究生数学建模竞赛,在报名这个比赛之前没有学习过相关知识,但是我想报名尝试一下,在报名以后会坚持学习很多相关知识。虽然不是每一次尝试都会成功,但在尝试的过程中我也能学习到很多知识。
自己还有哪些待提升的地方?
技术上,因为要兼顾科研、实验室项目和工程开发学习,目前对于有些知识的学习只停留在表面,只是对理论有一些了解,没有深入了解其源码,并且缺少一些实践经验。
性格上,有一点内向,在人多的陌生场合讲话会紧张。
这个缺点在我意识到以后我也会有意的改变和克制,原来刚上大学的时候在班里自我介绍都只能说说名字,现在经过准备已经可以在几十人的会议中作报告了。在今后我也会继续锻炼自己,争取让这个缺点消失。
让你感觉有挫折的事?
在我的叶片病害识别诊断项目中,对算法进行改进时,每天查阅了大量的资料,然后进行了很多的代码实践,但是最后得到的结果都不太理想。尤其是这一段时间的高强度工作,又没有明显的成果反馈,偶尔会有一些溃败感。
在我的三维体尺测量课题中,每天花费大量的时间对算法进行了改进,并且取得了一定的效果,但是论文每次投稿都被拒绝。这种付出了我大量心血和时间,但是结果却不太理想的事,可能会带给我一些挫败感。不过好在我没有放弃,现在的论文已经进入到最后的修订阶段了。
通常是怎么学习技术的?
这个分情况吧,如果是任务中急需使用的技术,我会直接去官网文档或者博客论坛学习对应的部分,尽可能先利用这个技术完成任务。如果不是特别着急,我会选择官方文档+博客+视频+书籍+源码的方式学习,通过博客或者视频首先建立一个概念体系,然后根据官方文档或者源码去深入学习。
职业规划and岗位理解
因为我个人的性格属于比较能静下心的,并且从小也对编程比较热爱,所以对于短期的目标是掌握好相关的技术基础,提升项目的开发经验,之后会去学习软件开发各个阶段的技能,比如市场分析,业务分析,结构设计,软件测试等等。
通过自己的努力为公司服务,在服务的过程中不断锻炼自己的能力和经验,有能力和经验以后承接更多的任务,能够带领团队更好的完成任务。
近期,我的计划是专攻我所面试的客户运营部需要的mysql、spring等技术,后续深入研究部门开发所需要的技术,让自己的技术有所成长和沉淀,可以伴随着公司一起成长。经过3年左右的时间,希望能承接部门中一些核心的项目和任务。经过5年左右的时间,希望精通开发各个阶段的技能,并且能够带领团队解决公司中难以解决的一些问题。
我理解Java后端开发主要负责处理应用程序的业务逻辑、数据库管理以及与前端的数据交互。我认为这个职位不仅要求技术能力,还要求对业务需求有一定的洞察力和能够进行有效沟通的能力,以确保技术解决方案能够满足企业的业务目标。
有无offer?
目前还没有收到offer,但是有一些阿里其他公司正在流程中,淘天是最想去最早投的,目前也是进度最快的,如果贵公司愿意给我发offer的话,我就把其他公司的流程结束了。
团队合作问题
这个我觉得分为队长和队员两部分来说。当我是队长的时候,我在安排任务的时候会尽可能地考虑到每个人的优缺点和他们的空闲时间,虽然还是会有人不按时完成任务。如果是因为能力不足或者时间不够,我们组内成员都会互相帮助。还有人是单纯对这个事情不感兴趣,消极怠工,最开始我们会劝他,没用的话就只能是人各有志了。
作为组员的话,我的首要任务就是完成好组长给我分配的任务,在自己有余力的情况下,帮助组内其他同学,承担一些额外的工作。如果给我分配的任务单纯靠我自己的努力无法完成,我会尽快向其他人求助,防止拖延项目进度。如果还是不能完成,我会向组长说明情况,是否能够更换一个更加适合我的任务。
学校和工作的区别
因为我没有真正出去实习工作过,有一些我通过跟别人沟通得出的想法。我认为在学校做项目的时候,更看重的是学习和做项目的过程,工作的话应该更看重的是做出来的项目是否满足需求。并且在学校做项目的时候对于极端情况考虑的会比较少,工作的话,比如写代码实现一个业务,需要考虑到各种不同用户的各种操作,并且还需要考虑网络传输等等可能出现的问题,确保项目上线后用户有一个良好的体验。
为什么选择淘天
我选择公司的主要标准是该公司的技术在行业领先,具有较好的职业发展机会,并且企业价值观是否与我个人相符。
作为一个技术人员,我渴望能够在一个不断推动技术发展、接触前沿技术的环境中工作。(淘天作为互联网的头部企业,具备行业内的顶尖技术,比如可以支撑双11超高并发的技术)
此外,我还希望能够在一家提供持续学习和成长机会的公司工作,我认为个人职业成长对于保持工作动力和创造力也是很重要的,而且在成长以后也可以更好的为公司服务。我了解到的淘天对于新人有”百年淘天“培养计划,还有内部学习平台等等。大厂新人培养体系之阿里巴巴 - 知乎 (zhihu.com)
最后我认为一家公司的价值观能够决定工作时是否有积极的工作环境。我对于阿里中客户第一的价值观是比较认可的。因为我个人在完成项目时不喜欢为了完成而完成,而是希望做的项目是真正可以使用,方便其他人使用的。而企业开发的项目就是为了让客户拥有更好的体验,这一点与我的想法比较一致。在这样的环境中,我也能更好的发挥我的潜力并且做出最大的贡献。
为什么选择淘天,是因为我从小到大用的最多的购物软件就是淘宝,所以对于淘宝本能的有一种向往,想去深入了解淘宝为什么可以发展的这么好。并且淘天的技术实力在互联网中也是很顶尖的,想去学习淘天中学习各种先进技术,比如可以支撑双11超高并发的技术。
最近了解到的新技术
最近了解到的应该是AI大模型方面。比如常听到的文心一言,讯飞星火,chatgpt这种自然语言相关的大模型,还有计算机视觉方面的SAM(segment everything)。因为我做过计算机视觉,所以对于SAM更加深入的了解过。SAM可以将图像中的一切对象分割出来,我自己也尝试使用过,对于图像中物体的分割性能确实很好,但是对于特定的使用场景或者特定的任务就有些力不从心了。比如我原来做过的叶片病害诊断,需要将叶片中的病斑分割出来,但是使用sam分割病斑的时候效果不如我提出来的算法。
所以我觉得在面对一项新技术的时,不能完全听从别人的介绍,也要有一些自己的实践和思考。
你从负责人身份经历中学到了什么?
学会了怎么带领团队去完成一项任务,而不是自己孤军奋战。比如我作为负责人带领团队进行叶片病害诊断的项目中,我需要根据每个人的时间和性格、能力去尽可能分配他们能够完成的任务,比如其中有一项数据标注的任务,就会分配给时间比较多的同学。
并且经过带领团队的历练,我觉得我的抗压能力和解决问题的能力也有了一定的提升。当成员的时候完成好分配的任务即可,但是当负责人就需要考虑项目进度,项目实现的效果等等问题,感觉压力会更大一些。
项目中遇到难题怎么办?
首先是对遇到的难题进行分析,思考这个难题怎么去解决,根据思考的结果去网上查询一些相关的解决方案,如果依靠自己和网上的方案都不能解决这个问题,会将遇到的问题和自己的思考整理好,向其他同学请教讨论。如果还是不能解决问题,会尽快找老师请教,避免在一个问题上耽误太长时间,拖延项目进度。
怎么体现沟通能力和推动力?
在我带领团队进行植物叶片病害诊断项目的时候,我会主动跟我的成员沟通,确保每个人充分了解项目内容,能理解他们自己的任务以及一些时间节点。还会定期开会讨论项目进度和大家遇到的问题,一起讨论解决项目实现中的难题。通过我们的努力,在项目截止日期前成功改进算法并且发表一篇SCI论文。
你最仰慕的人
我最仰慕的人是我的母亲,因为我对他印象最深的就是坚持,不轻言放弃。正是因为受我母亲的影响,我现在对待一件事的时候,哪怕这个事很难完成,我也会尽我的努力去尝试,这样就算最后失败了,我也不会特别沮丧,因为我努力过。
你认为程序员的三大品德
我认为是懒惰(自动化)、急躁(求极致)和傲慢(高标准)。
我认为一个优秀程序员的懒惰不是不想做事,而是希望少做事而达到一样的目标。比如让事务性的工作自动化,减少重复造轮子,写出简洁的代码和完整有效的文档,让别人更好的使用。
急躁是追求极致的品质,是对于解决问题不够有效的一种不容忍的态度。比如写出更优秀性能更好的代码,积极寻求更好的算法和方案,降低代码运行的时间复杂度,真正尽快的解决问题。
傲慢其实是对自己的高标准和严要求。要求自己持续学习,保持技术上的自信,保持谦逊,对自己的程序要求足够高的要求,成为团队合作者和问题解决者。
实习为了什么?为什么选择这个岗位?
因为我很热爱编程,希望我写出来的代码是实际有用的。在学校工程方面的项目比较少,真正有意义的实践机会也比较少。
我认为实习是一个很好的机会,能够将我在学校学到的理论知识应用到实践中。特别是在贵公司,有很多先进的技术和项目。如果能在这样的环境下工作学习,可以让我快速成长,提升我的编程能力和团队协作能力。我也希望毕业之后能够留在贵公司工作。
十年后会变成什么样的程序员?
我希望我可以具有程序员的三大美德,变成技术方面的大牛,能够解决各种复杂场景的问题,并且可以带领团队更好的完成各种业务,帮助团队成员成长。
这份工作支持你变成那样么?
我认为是支持的,因为贵公司有业界最先进的工程技术和较好的培养计划。
你的舍友与组员如何评价你?
我对我舍友说过的一句话印象特别深刻,他说“是真正的研究生”,我的研究生阶段每天都很忙碌,研一的时候要兼顾上课、科研和竞赛,研二的时候要承担实验室项目任务,完成自己的科研任务,还要抽空学习工程开发方面的知识。每天都过的很充实,也学习到了很多知识,成长的速度也很快。
研究生意味着什么?(为什么要读研?)
我认为研究生不仅意味着可以深入学习专业知识,更是一个人成长的重要阶段。在研究生期间有机会接触到计算机领域的前沿科技,比如人工智能、深度学习等。除了专业技能的提升,通过参与课题研究和项目实践,锻炼了我独立思考、提出问题、分析问题和解决问题的能力,同时也提升了我的抗压能力。
理想的上班环境?
我理想的工作环境是鼓励团队合作和沟通的。一个团队成员之间能够自由交流想法,不仅可以提升工作效率,还能激发出一些创新点。
为什么选择企业而不是体制内
因为我比较喜欢编程,比较喜欢做工程相关的。想对企业来说,在体制内这种机会比较少。
地点在杭州,你觉得如何
我认为杭州非常好,我在投简历的时候就选择了杭州。我觉得长三角地区的经济向内辐射,很有前景,加上这边计算机环境和氛围很好,所以我也很想到这个地方定居。
我的父母也很支持我去杭州,我父母原来都在南方工作过,后来迫不得已回到了北方,他们以后也愿意一起来杭州定居。
有没有和同学发生过激烈的言语冲突?
没有。我个人的性格是属于比较平和的,很少有跟人生气的时候。而且我认为吵架并不能解决问题,反而不如心平气和的把事情说明白,说清楚,这样的效果可能会更好一些。
和人沟通的风格?
我的沟通风格比较倾向于清晰和直接。在团队合作讨论过程中,我会直截了当的说明自己的看法和观点,在给成员安排任务的时候也会详细说明任务的内容和截止日期。
保研是怎么决定的?有没有特别想要过什么东西?如何得到的?
我在读大一的时候就有读研究生的想法,之后了解到了保研的一些规则和政策,我会根据政策中的要求有针对性的参加一些比赛和科研项目,提高保研的分数,最后也是以保研成绩第一的名次成功保研。
人生的至暗时刻,怎么克服?
首先是接受自己的情绪吧,然后跟我的家人和朋友交流,向他们寻求一些安慰和支持。如果是一些困难但又要完成的事情,可以设定一些相对容易实现的小目标,一步一步的实现。
AI和程序员的关系,会不会取代,AI代码能力的提升是利是弊
我认为AI是程序员的助手,并不会取代程序员,AI的代码能力提升我认为是利大于弊。现在的AI大模型虽然可以写出很多代码,但是这些代码都是一些逻辑性比较弱的,或者是常见的代码,对于简单的任务和重复的任务来说,使用AI可以减少重复造轮子所浪费的时间,但对于实际开发中的任务AI是难以理解的,这一部分还是需要程序员来完成。
入职后会遇到的困难
我觉得入职后最大的挑战可能是需要迅速适应部门的技术栈和工具。虽然我有过一些Java开发的经验,但是部门可能会有自己侧重的技术。为了克服这个困难,我在一面的时候有问过面试官我需要提前学习什么,最近也有在深入了解面试官所提到的内容。
除了技术上的困难,作为团队的新成员,可能需要一段时间来适应团队沟通和协作。我的计划是主动参与到一些团队活动中去,尽快的融入到团队中。
如何协同?
首先是创建了QQ群聊,并且每周会有固定的会议时间,确保所有成员都能及时更新进展和分享问题。面对不同意见时,我会邀请相关成员开会讨论,共同找到最佳的解决方案。