成都好的网站建设公司企业网站 响应式
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:11
当前位置: 首页 > news >正文
成都好的网站建设公司,企业网站 响应式,要做个卖东西网站怎么做,wordpress用户注册登录插件说在前面 在40岁老架构师尼恩的#xff08;50#xff09;读者社群中#xff0c;经常有小伙伴#xff0c;需要面试美团、京东、阿里、 百度、头条等大厂。 下面是一个小伙伴成功拿到通过了美团一面面试#xff0c;现在把面试真题和参考答案收入咱们的宝典。 通过美团一面…说在前面 在40岁老架构师尼恩的50读者社群中经常有小伙伴需要面试美团、京东、阿里、 百度、头条等大厂。 下面是一个小伙伴成功拿到通过了美团一面面试现在把面试真题和参考答案收入咱们的宝典。 通过美团一面真题 大家可以看看收个优质Offer需要学点啥 总之光代码漂亮不够 面试还得会吹。 这里把题目以及答案经过整理和梳理之后收入咱们的《尼恩Java面试宝典PDF》 V121版本供后面的小伙伴参考提升大家的 3高 架构、设计、开发、吹牛水平。 《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF请到公号【技术自由圈】获取 文章目录 说在前面美团一面1、redis基本数据类型应用场景2、redis如何实现共同关注补充Set集合三个特殊方法 sinter 、sunion 、sdiffsinter 交集的示例sunion 并集的示例sdiff 差集的示例 3、redis持久化AOFRDB会丢数据吗1.AOFAppend-Only File持久化2.RDBRedis DataBase持久化补充AOF 配置AOF的优缺点RDB-AOF混合持久化 4、redis穿透击穿雪崩解决缓存穿透解决措施缓存击穿解决措施缓存雪崩解决措施缓存更新策略合理的缓存策略 5、redis大Key怎么处理拆分数据使用数据压缩使用数据分片定期清理使用内存优化的数据结构数据预热和缓存策略 6、redis分布式锁Zookeeper分布式锁怎么选择性能一致性部署复杂性可用性应用已有基础数据持久性需求社区支持 7、说说熔断与限流一、熔断二、限流 8、为什么kafka多用于消息中转很少用于实时计算9、说说kafka高可用高吞吐高可用高吞吐 10、说说kafka不重不丢11、说说kafka消费端幂等性12、说说kafka消费者群组13、说说kafka生产端分配路由14、说说mysql索引为什么B树15、说说主键索引二级索引1. 主键索引2. 二级索引 16、说说mysql ACID17、mysql事务隔离级别RR解决幻读吗什么场景下会幻读1. 什么是幻读2. RR隔离级别如何解决幻读可能出现幻读问题 18、MVCC事务版本号怎么生成存在哪里19、说说binlogredologundolog1. Binlog二进制日志2. Redo Log重做日志3. Undo Log撤销日志 20、挂了用什么log主从同步用什么log21、说说binlog的两阶段提交1. 预提交阶段2. 确认提交阶段 22、算法题买卖股票描述思路实现 尼恩说在最后尼恩技术圣经系列PDF 美团一面 1、redis基本数据类型应用场景 String字符串适用于存储文本、数字等数据。常见用途包括缓存、计数器、会话管理等。Hash哈希表适合存储对象如用户数据、商品信息的多个字段及其值。能快速检索或修改字段值。List列表用于保存有序的元素序列。适用于实现消息队列、栈、发布订阅等功能。Set集合用于保存不重复的元素。适用于存储标签、好友列表等也可用于计算交集、并集等操作。Sorted Set有序集合类似于 Set但每个元素都有一个分数可用分数对元素进行排序。适用于实现排行榜、优先级队列等。Bitmap位图适合存储布尔值可用于追踪用户在线状态、用户活跃度等。能执行位运算以统计和查询状态。HyperLogLog用于估算集合中不重复元素的数量适用于统计 UV独立访客数等场景。Geospatial地理空间用于存储地理位置信息支持距离计算和附近位置的查询。适合实现地图应用、位置服务等。Pub/Sub发布订阅用于实现消息发布和订阅机制适用于构建实时通知、事件驱动系统等。 2、redis如何实现共同关注 要实现共同关注功能如社交网络中的好友关系可以利用 Redis 数据结构来存储关注关系。 给个示例 假设存在两个用户用户 A 和用户 B他们都可以关注其他用户。我们希望找到他们共同关注的用户。 使用集合Set存储用户的关注列表 用户A的关注列表sadd userA_following userC userD userE 用户B的关注列表sadd userB_following userD userE userF找出用户 A 和用户 B 的共同关注 使用集合的交集操作sinter找出两个用户的共同关注 sinter userA_following userB_following该操作将返回一个集合包含用户 A 和用户 B 共同关注的用户在此示例中是 userD 和 userE。 可以采用类似方法查找其他用户的共同关注或执行其他操作如取消关注、添加新关注等。 补充Set集合三个特殊方法 sinter 、sunion 、sdiff redis 支持 Set集合的数据存储其中有三个比较特殊的方法 sinter key [key …] 查看一个集合的全部成员该集合是所有给定集合的交集。sunion key [key …] 查看一个集合的全部成员该集合是所有给定集合的并集。sdiff key [key …] 查看所有给定 key 与第一个 key 的差集 sinter 交集的示例 redis SMEMBERS group_1
- LI LEI
- TOM
- JACKredis SMEMBERS group_2
- HAN MEIMEI
- JACKredis SINTER group_1 group_2 # 取的是交集的数据
- JACK sunion 并集的示例 redis SMEMBERS songs
- Billie Jeanredis SMEMBERS my_songs
- Believe Meredis SUNION songs my_songs # 取的是集合的并集数据
- Billie Jean
- Believe Me sdiff 差集的示例 redis SMEMBERS peter_movies
- bet man
- start war
- 2012redis SMEMBERS joe_movies
- hi, lady
- Fast Five
- 2012redis SDIFF peter_movies joe_movies # 取的是两个集合的差集
- bet man
- start war3、redis持久化AOFRDB会丢数据吗 两种持久化策略 AOFRDB 1.AOFAppend-Only File持久化 a. AOF持久化以追加的方式记录每个写操作包括SET、INCR等到一个日志文件中该文件包含了恢复数据所需的所有写操作。 b. AOF持久化可以配置为每秒同步一次默认配置或者根据需要更频繁地同步。 c. 由于AOF记录了每个写操作通常情况下不会丢失数据即使Redis宕机也可以通过AOF文件来完全恢复数据。 2.RDBRedis DataBase持久化 a. RDB持久化是通过周期性快照快照整个数据集到磁盘的方式。 b. RDB 文件包含特定时间点数据集的快照因此两次快照之间的数据更改可能会丢失。 c. 默认情况下Redis 每隔一段时间可配置执行一次 RDB 快照。 若 Redis 在两次快照间崩溃可能导致数据丢失。 总的来说 AOF持久化默认会丢失1s数据也可以配置为每次都刷盘这样不会丢失数据因为它记录了每个写操作但会有一定的数据恢复成本。RDB持久化在快照间可能会丢失数据但因为RDB文件只包含快照时的数据所以通常比AOF更快速。 补充AOF 配置 在 redis.conf 配置文件的 APPEND ONLY MODE 下 ①、appendonly默认值为no也就是说redis 默认使用的是rdb方式持久化如果想要开启 AOF 持久化方式需要将 appendonly 修改为 yes。 AOF 保存文件的位置和 RDB 保存文件的位置一样都是通过 redis.conf 配置文件的 dir 配置文件的位置. ②、appendfilename aof文件名默认是appendonly.aof ③、appendfsyncaof持久化策略的配置 no表示不执行fsync由操作系统保证数据同步到磁盘速度最快但是不太安全always表示每次写入都执行fsync以保证数据同步到磁盘效率很低everysec表示每秒执行一次fsync可能会导致丢失这1s数据。通常选择 everysec 兼顾安全性和效率。 ④、no-appendfsync-on-rewrite在aof重写或者写入rdb文件的时候会执行大量IO此时对于everysec和always的aof模式来说执行fsync会造成阻塞过长时间no-appendfsync-on-rewrite字段设置为默认设置为no。如果对延迟要求很高的应用这个字段可以设置为yes否则还是设置为no这样对持久化特性来说这是更安全的选择。 设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入默认为no建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。默认值为no。 ⑤、auto-aof-rewrite-percentage默认值为100。aof自动重写配置当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍设置为100时自动启动新的日志重写过程。 ⑥、auto-aof-rewrite-min-size64mb。设置允许重写的最小aof文件大小避免了达到约定百分比但尺寸仍然很小的情况还要重写。 ⑦、aof-load-truncatedaof文件可能在尾部是不完整的当redis启动的时候aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后尤其在ext4文件系统没有加上dataordered选项出现这种现象 redis宕机或者异常终止不会造成尾部不完整现象可以选择让redis退出或者导入尽可能多的数据。如果选择的是yes当截断的aof文件被导入的时候会自动发布一个log给客户端然后load。如果是no用户必须手动redis-check-aof修复AOF文件才可以。默认值为 yes。 AOF的优缺点 优点 ①、AOF 持久化的方法提供了多种的同步频率即使使用默认的同步频率每秒同步一次Redis 最多也就丢失 1 秒的数据而已。 ②、AOF 文件使用 Redis 命令追加的形式来构造因此即使 Redis 只能向 AOF 文件写入命令的片断使用 redis-check-aof 工具也很容易修正 AOF 文件。 ③、AOF 文件的格式可读性较强这也为使用者提供了更灵活的处理方式。例如如果我们不小心错用了 FLUSHALL 命令在重写还没进行时我们可以手工将最后的 FLUSHALL 命令去掉然后再使用 AOF 来恢复数据。 缺点 ①、对于具有相同数据的的 RedisAOF 文件通常会比 RDF 文件体积更大。 ②、虽然 AOF 提供了多种同步的频率默认情况下每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时RDB 比 AOF 具好更好的性能保证。 ③、RDB 使用快照的形式来持久化整个 Redis 数据而 AOF 只是将每次执行的命令追加到 AOF 文件中因此从理论上说RDB 比 AOF 方式更健壮。官方文档也指出AOF 的确也存在一些 BUG这些 BUG 在 RDB 没有存在。 那么对于 AOF 和 RDB 两种持久化方式我们应该如何选择呢 如果可以忍受一小段时间内数据的丢失毫无疑问使用 RDB 是最好的定时生成 RDB 快照snapshot非常便于进行数据库备份 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快而且使用 RDB 还可以避免 AOF 一些隐藏的 bug否则就使用 AOF 重写。但是一般情况下建议不要单独使用某一种持久化机制而是应该两种一起用在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。Redis后期官方可能都有将两种持久化方式整合为一种持久化模型。 RDB-AOF混合持久化 在Redis4.0之后在RDB和AOF两种持久化方式之外又新增了RDB-AOF混合持久化方式。 这种方式结合了RDB和AOF的优点既能快速加载又能避免丢失过多的数据。 具体配置为 aof-use-rdb-preamble设置为yes表示开启设置为no表示禁用。 当开启混合持久化时主进程先fork出子进程将现有内存副本全量以RDB方式写入aof文件中然后将缓冲区中的增量命令以AOF方式写入aof文件中写入完成后通知主进程更新相关信息并将新的含有 RDB和AOF两种格式的aof文件替换旧的aof文件。 简单来说混合持久化方式产生的文件一部分是RDB格式一部分是AOF格式。 这种方式优点我们很好理解缺点就是不能兼容Redis4.0之前版本的备份文件了。 4、redis穿透击穿雪崩解决 缓存穿透解决措施 a. Bloom Filter利用布隆过滤器筛选出不在缓存中的请求以降低对数据库的请求压力。 b. 空值缓存虽数据库中不存在该数据但仍将其缓存但设置较短的过期时间以防频繁查询。 c. 缓存空对象当数据库查询结果为空时也将该结果缓存但设定较短的过期时间避免重复查询。 缓存击穿解决措施 a. 互斥锁采用互斥锁保护缓存当缓存失效时只允许一个请求查询数据库其他请求等待结果避免多个请求同时击穿缓存。 b. 热点数据预热定期或启动时预先加载热门数据至缓存防止因突发大量请求导致缓存击穿。 缓存雪崩解决措施 a. 缓存失效时间随机性为缓存失效时间增加一定随机性使缓存不会同时失效减轻对数据库的并发请求压力。 b. 持久化缓存利用 AOF 和 RDB 的持久化机制确保缓存数据可靠性即使在缓存雪崩情况下也能从持久化数据中恢复。 c. 多级缓存采用多级缓存如本地内存缓存、分布式缓存、CDN 等分担缓存压力使某一缓存层发生雪崩时其他层仍能提供服务。 缓存更新策略 a. 异步刷新缓存失效后后台异步更新缓存避免请求等待缓存更新。 b. 加锁更新缓存失效时仅允许一个请求查询数据库并更新缓存其他请求等待结果。 合理的缓存策略 a. 根据数据访问模式和业务需求选择合适的缓存策略如 LRU最近最少使用、LFU最不常使用、TTLTime To Live等。 5、redis大Key怎么处理 Redis中的大Key通常指缓存键对应的值较大可能包含大型数据结构、大量文本或二进制数据等。这类数据会导致内存占用过高进而影响性能。给大家一些处理Redis大Key的参考方法 拆分数据 a. 如有条件将大型数据拆分成多个小型数据并分别存储在独立的键中。这能降低单个键的大小减少内存占用。 b. 例如若某个键存储了大型 JSON 对象可将其拆分为多个子键每个子键存储 JSON 对象的部分数据。 使用数据压缩 a. 在存储文本或二进制数据之前可对其进行压缩在读取时再解压缩。虽然 Redis 本身不支持数据压缩但可在应用层实现压缩和解压缩操作。 使用数据分片 a大 Key 是由多个小 Key 组成的集合可以使用 Redis 的数据分片或分区技术将数据分布在多个 Redis 实例中每个实例负责一部分数据。 这有助于减轻单个实例的内存压力。 定期清理 a. 若大 Key 生命周期有限可以定期清理不再需要的数据以释放内存。 b. 使用DEL命令删除不再需要的大Key。 使用内存优化的数据结构 对于大型集合或列表可以考虑使用 Redis 的内存优化数据结构如 HyperLogLog、Redis Streams 等以降低内存占用。 数据预热和缓存策略 如果大 Key 是在系统启动时加载的可以实施数据预热策略提前将热门数据加载到缓存中以减轻启动时的内存压力。 6、redis分布式锁Zookeeper分布式锁怎么选择 给大家一些选择是需要考虑的因素在什么情况用哪种分布式锁是更优选择。 性能 a. 通常情况下Redis 的性能优于 ZooKeeper因为它采用内存存储系统而 ZooKeeper 采用磁盘存储。 b. 如果你追求高性能的分布式锁Redis 是更好的选择。 一致性 a. ZooKeeper 提供强一致性适合对一致性要求较高的分布式应用如协调和选举等。 b. Redis 的分布式锁在某些情况下可能出现失效或死锁因为它是基于主从复制的。 部署复杂性 a. ZooKeeper 需要独立的 ZooKeeper 集群需进行维护和管理。 b. Redis 部署相对简单特别是若你在应用中已使用 Redis。 可用性 a. Redis 扩展和部署较容易因此便于实现高可用性。 b. ZooKeeper 的部署和维护较为复杂尤其在多数据中心环境中。 应用已有基础 a. 若你在应用中已使用 Redis添加 Redis 分布式锁较为容易集成。 b. 若应用已使用 ZooKeeper选择 ZooKeeper 分布式锁更为合适。 数据持久性需求 a. 需更强数据持久性和一致性时可考虑使用 ZooKeeper。 b. Redis 提供持久性但通常在性能和可用性之间作出权衡。 社区支持 Redis 和 ZooKeeper 均有活跃的社区支持需根据具体需求评估社区支持和文档资源。 综合考虑以上因素若应用需高性能分布式锁且可容忍一定程度的一致性弱点可选 Redis 分布式锁。若需强一致性和更复杂分布式协同操作ZooKeeper 分布式锁更适合。 7、说说熔断与限流 在分布式系统中熔断和限流是两种关键技术它们有助于提高系统的可用性和稳定性。 一、熔断 熔断机制旨在防止系统出现雪崩效应。当某个服务或组件的错误率超过设定阈值熔断器就会启动阻止进一步的请求访问该服务以避免更多系统部分崩溃。熔断器开启后会定时检查服务可用性一旦恢复正常便关闭熔断器允许请求再次访问。 熔断的好处包括 避免错误服务波及整个系统。减轻故障服务负担减少不必要请求。促使系统恢复正常运行而非持续崩溃。
- 熔断器实现
import java.util.concurrent.TimeUnit;
public class CircuitBreaker { private final ThreadPoolExecutor executor; private final Semaphore permit; private final long timeout;public CircuitBreaker(int maxThreads, long timeout, TimeUnit unit) { this.executor new ThreadPoolExecutor(maxThreads, maxThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); this.permit new Semaphore(1); this.timeout timeout; }public void execute(Runnable command) { permit.acquire(); try { executor.execute(command); } catch (Exception e) { // 处理异常例如记录日志、发送告警等 System.err.println(Error occurred while executing command: e.getMessage()); } finally { permit.release(); } }public void reset() { executor.shutdown(); try { if (!executor.awaitTermination(timeout, TimeUnit.MILLISECONDS)) { // 超过恢复时间仍然无法恢复则考虑进行降级或熔断 System.err.println(Failed to reset circuit breaker); } } catch (InterruptedException e) { // 等待过程中出现中断表示恢复失败 System.err.println(Interrupted while waiting for circuit breaker reset: e.getMessage()); } executor new ThreadPoolExecutor(executor.getPoolSize(), executor.getPoolSize(), 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }
}2.使用示例 public class CircuitBreakerDemo { public static void main(String[] args) { CircuitBreaker circuitBreaker new CircuitBreaker(10, 5000, TimeUnit.MILLISECONDS);for (int i 0; i 10; i) { circuitBreaker.execute(() - { System.out.println(Executing command i); throw new RuntimeException(模拟异常); }); }circuitBreaker.reset();for (int i 0; i 10; i) { circuitBreaker.execute(() - { System.out.println(Executing command i); }); } }
}二、限流 限流机制旨在控制服务请求速率防止系统同时承受过多请求。根据应用需求限流可以有多种实现方式如 固定速率限流每秒最多允许N个请求。漏桶算法请求以固定速率进入“桶”若“桶”满多余请求将被丢弃。令牌桶算法每个请求需获取一个令牌令牌以固定速率生成若无令牌请求将被拒绝。 限流的好处包括 防止大规模请求突然涌入导致系统过载。控制系统负载保护后端服务免受过多请求压力。提供一种方式来保护资源如API免受滥用和DDoS攻击。 - 定义一个 TokenBucket 类
import java.util.concurrent.TimeUnit;
public class TokenBucket { private final long capacity; private final long tokensPerSecond; private long lastRefillTime; private long tokens;public TokenBucket(long capacity, long tokensPerSecond) { this.capacity capacity; this.tokensPerSecond tokensPerSecond; this.lastRefillTime System.currentTimeMillis(); this.tokens capacity; }public boolean consume(long tokens) { if (tokens capacity) { return false; }refill(); if (tokens tokens) { tokens - tokens; return true; } else { return false; } }private void refill() { long now System.currentTimeMillis(); long elapsed now - lastRefillTime; long newTokens elapsed * tokensPerSecond; tokens Math.min(capacity, tokens newTokens); lastRefillTime now; }
}2. 使用示例 public class Main { public static void main(String[] args) { TokenBucket bucket new TokenBucket(10, 2);System.out.println(bucket.consume(5)); // 消耗 5 个令牌返回 True try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(bucket.consume(6)); // 消耗 6 个令牌返回 False try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(bucket.consume(2)); // 消耗 2 个令牌返回 True }
}在这个例子中我们创建了一个 TokenBucket 类通过 consume 方法限制每秒请求的次数。每次调用 consume 方法时会先检查当前令牌是否足够如果不够则返回 False表示限流。如果足够则消耗令牌并返回 True。在 refill 方法中我们会根据时间间隔和每秒添加的令牌数来补充令牌。 这个简单的限流器可以用于保护 Java 系统的瓶颈部分防止流量过大导致系统崩溃。在实际应用中可以根据需求进行优化和扩展。 8、为什么kafka多用于消息中转很少用于实时计算 持久性存储Kafka 作为一种持久性消息队列将消息存储在磁盘上确保数据不会因消费者未能及时处理而丢失。这使得 Kafka 非常适合作为消息中转让消费者能在任意时间点访问消息而不仅限于实时计算。消息存储和检索Kafka 的主要功能是存储和检索消息而非执行复杂实时计算。它具备高吞吐量和低延迟的消息存储与检索能力但并未提供计算框架因此在实时计算方面相对薄弱。数据保留Kafka 支持根据不同策略保留消息如时间或存储大小。这使得 Kafka 适用于长期数据存储和数据历史查询而不仅仅是实时计算。消息分发和复制Kafka 具有强大的消息分发和复制机制确保消息可靠地传递到多个消费者或订阅者。这使得 Kafka 成为消息分发的理想选择但它并不提供实时计算所需的状态管理和处理。 9、说说kafka高可用高吞吐 高可用 分布式架构Kafka 作为一个分布式系统可部署在多台服务器上从而具备冗余性。当一台服务器出现故障时其他服务器能够继续运行确保消息流的可用性。复制和副本Kafka 采用分区组织消息每个分区都有多个副本。这意味着消息在多个服务器上进行复制以防数据丢失。若某个副本不可用其他副本仍可提供数据。ZooKeeperKafka 利用 Apache ZooKeeper 管理集群元数据和协调任务。ZooKeeper 提供了分布式锁和选举机制确保 Kafka 集群内各组件协同工作。消费者位移Kafka 记录了消费者在各分区的位移这意味着即使消费者出现故障也可以从上次中断的地方继续消费消息避免数据丢失。 高吞吐 分区Kafka 通过分区实现水平扩展。每个分区可由不同服务器处理从而平均分配负载提高吞吐量。批处理和零拷贝Kafka 采用批处理机制降低磁盘和网络开销。此外它还利用零拷贝技术将数据从生产者传输至消费者减少 CPU 和内存开销。压缩Kafka 支持消息压缩缩小数据传输尺寸提高吞吐量。持久性Kafka 的消息持久化至磁盘允许在多个消费者之间共享数据并确保即使消费者离线数据也不会丢失。分布式部署Kafka 可部署在多台服务器上充分利用硬件资源提供高吞吐量。 import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringValueSerializer; public class KafkaExample { public static void main(String[] args) { // 创建生产者 KafkaProducerString, String producer new KafkaProducer( new StringValueSerializer(), new StringValueSerializer() );// 创建消费者 KafkaConsumerString, String consumer new KafkaConsumer( new StringValueSerializer(), new StringValueSerializer() );// 发送消息 producer.send(test-topic, Hello, Kafka!);// 接收消息 consumer.subscribe(test-topic); while (true) { ConsumerRecordsString, String records consumer.poll(100); for (ConsumerRecordString, String record : records) { System.out.printf(Received message: %s%n, record.value()); } } }
}综上所述Kafka 实现高可用、高吞吐的主要手段包括分布式架构、顺序读写、零拷贝、文件分段、批量发送和数据压缩等技术。通过这些技术和优化Kafka 能够在大规模消息处理场景下表现出优异的性能。 10、说说kafka不重不丢 Kafka 致力于实现不重不丢这意味着它努力确保消息不会被重复传递也不会在传递过程中丢失。为了实现这一目标Kafka 采用了以下关键机制 消息复制和副本Kafka 使用多个副本来保存消息每个分区的消息都有多个副本分布在不同的服务器上。这样即使某个服务器故障仍然可以从其他副本中获取消息。消费者位移Kafka 记录了每个消费者在每个分区中的位移offset表示消费者已经处理到哪个位置的消息。消费者可以定期提交位移以确保它们不会重复消费消息。生产者确认机制Kafka 生产者在将消息发送到服务器后会等待服务器的确认acknowledgment。只有当服务器确认接收到消息后生产者才会认为消息已经成功发送。事务支持Kafka 提供了事务支持允许生产者在发送消息时执行事务性操作。这意味着消息要么全部成功发送要么一个都不发送以确保不重不丢。幂等性生产者Kafka 生产者支持幂等性即使生产者发送相同的消息多次只有一次会生效有助于避免重复消息。 以下是一个简单的 Java 代码示例实现了 Kafka 生产者和消费者功能同时展示了如何确保消息不重复和不丢失。 生产者端Producer.java import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer; import java.time.Duration;
import java.util.Properties; public class Producer { public static void main(String[] args) { // 配置生产者参数 Properties props new Properties(); props.put(bootstrap.servers, localhost:9092); props.put(key.serializer, org.apache.kafka.common.serialization.StringSerializer); props.put(value.serializer, org.apache.kafka.common.serialization.StringSerializer);// 创建生产者实例 ProducerString, String producer new KafkaProducer(props);// 发送消息 for (int i 0; i 10; i) { String message Hello, Kafka! i; producer.send(new ProducerRecord(test-topic, message)); System.out.printf(Sent message: %s%n, message); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }// 关闭生产者 producer.close(); }
}这个生产者实例使用了 KafkaProducer 类并发送了 10 条消息到名为 test-topic 的 topic。在 main 方法中调用 send 方法发送消息并在发送消息后打印消息内容。生产者在运行过程中会持续发送消息。当需要结束程序时调用 close 方法关闭生产者。 消费者端Consumer.java import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.common.serialization.StringSerializer; import java.time.Duration;
import java.util.Collections;
import java.util.Properties; public class Consumer { public static void main(String[] args) { // 配置消费者参数 Properties props new Properties(); props.put(bootstrap.servers, localhost:9092); props.put(key.serializer, org.apache.kafka.common.serialization.StringSerializer); props.put(value.serializer, org.apache.kafka.common.serialization.StringSerializer); props.put(enable.auto.commit, true); props.put(auto.commit.interval.ms, 1000);// 创建消费者实例 ConsumerString, String consumer new KafkaConsumer(props);// 订阅 topic consumer.subscribe(Collections.singletonList(test-topic));// 消费消息 while (true) { ConsumerRecordsString, String records consumer.poll(Duration.ofMillis(1000));for (ConsumerRecordString, String record : records) { System.out.printf(offset %d, key %s, value %s%n, record.offset(), record.key(), record.value()); } }// 关闭消费者 consumer.close(); }
}这个消费者实例使用了 KafkaConsumer 类并订阅了名为 test-topic 的 topic。在 main 方法中使用 poll 方法轮询消息并在接收到消息时打印 offset、key 和 value。消费者在运行过程中会持续接收和处理消息。当需要结束程序时调用 close 方法关闭消费者。 11、说说kafka消费端幂等性 Kafka 消费者端的幂等性是指消费者能够处理来自 Kafka 主题的消息而不会导致重复数据或意外的结果。保持幂等性对于确保数据处理的正确性和稳定性至关重要。 以下是一些建议和方法用于实现 Kafka 消费者端的幂等性 消费者位移管理Kafka 消费者应恰当管理位移以避免消息的重复处理。消费者应定期提交已成功处理的消息的位移以确保它们不会再次消费相同的消息。消息处理的幂等性消费者的消息处理逻辑应是幂等的即无论处理相同的消息一次还是多次结果应相同。这可以通过设计消息处理逻辑来实现例如检查消息的唯一标识符以避免重复插入相同的数据。幂等性标识符在某些处理场景中可以在消息中包含幂等性标识符。消费者在处理消息之前检查这个标识符以确保不会重复处理相同的消息。事务性处理Kafka 支持事务消费者可使用事务性处理来确保消息的幂等性。在处理消息之前消费者可以启动事务并在成功处理后提交事务。这样确保消息只会被处理一次。异常处理消费者需正确处理异常情况。如果消息处理失败消费者应能够重新处理消息而不引入额外的副作用。这可能涉及到将消息从未处理状态切换到已处理状态的机制。幂等性测试对于关键的消息处理逻辑建议编写单元测试来验证其幂等性。这些测试可以模拟重复消息处理以确保不会引入重复数据。 以下是一个简单的 Java 示例展示了如何实现 Kafka 消费端的幂等性 import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer; import java.time.Duration;
import java.util.Collections;
import java.util.Properties; public class KafkaConsumerIdempotenceDemo { public static void main(String[] args) { // 配置消费者参数 Properties props new Properties(); props.put(bootstrap.servers, localhost:9092); props.put(group.id, test-group); props.put(key.deserializer, org.apache.kafka.common.serialization.StringDeserializer); props.put(value.deserializer, org.apache.kafka.common.serialization.StringDeserializer); props.put(auto.offset.reset, earliest);// 创建消费者实例 KafkaConsumerString, String consumer new KafkaConsumer(props);// 订阅 topic consumer.subscribe(Collections.singletonList(test-topic));// 消费消息 while (true) { ConsumerRecordsString, String records consumer.poll(Duration.ofMillis(100)); for (ConsumerRecordString, String record : records) { // 处理消息 processMessage(record.value());// 提交偏移量 consumer.commit(record.offset()); } }// 关闭消费者 consumer.close(); }private static void processMessage(String message) { // 实现幂等处理逻辑例如使用数据库事务或悲观锁 // 这里仅作为示例模拟数据库操作 System.out.println(Processing message: message); }
}在这个示例中我们创建了一个 Kafka 消费者订阅了名为 test-topic 的 topic。在 poll 方法中获取消息并对每条消息进行幂等处理。处理完成后使用 commit 方法提交消费偏移量。 需要注意的是这个示例仅实现了消费端的幂等性并未涉及生产端的消息幂等。 在实际应用中为了确保消息的幂等性需要在生产端和消费端都进行相应的处理。此外Kafka 的幂等性仅保证了单个分区内的消息不重复不同分区之间仍有可能出现重复消息。如需保证多个分区的幂等性可以考虑使用 Kafka 的事务功能。 12、说说kafka消费者群组 Kafka 消费者群组是 Kafka 中用于协同消费主题中消息的机制。它允许多个消费者协同工作以从一个或多个主题中消费消息。 多个消费者一个消费者群组可以包括多个消费者。这些消费者可以在不同的应用程序或服务器上运行。主题分区Kafka 主题通常被划分为多个分区每个分区包含一部分消息。消费者群组可以同时消费多个分区中的消息。负载均衡Kafka 自动分配分区给消费者以实现负载均衡。每个分区通常只分配给一个消费者来避免重复消费。水平扩展通过增加消费者可以水平扩展消费者群组以处理更多的消息。消费者位移管理Kafka 为每个消费者群组中的消费者维护位移offset表示它们在每个分区中的消费位置。这确保了消费者能够从上次停止的位置继续消费。消费者协作在同一个消费者群组中每个分区只能由一个消费者消费。这有助于避免重复消费。消息处理并行性每个消费者可以在独立的线程中处理消息从而提高消息的处理并行性。自动重平衡如果有新的消费者加入或旧的消费者退出Kafka 自动触发群组的重平衡以重新分配分区确保负载均衡。消费者状态监控Kafka 提供监控工具来跟踪消费者群组的状态包括消费速度和位移。 13、说说kafka生产端分配路由 Kafka 生产端的主要职责是将消息发送至 Kafka 集群并确保消息被正确路由至适宜的主题和分区。在这一过程中Kafka 采用了分区策略来对消息进行分区从而实现消息在各个分区间的均衡分布。 以下是一些相关概念 主题Kafka 中的主题作为消息的逻辑容器生产者可以将消息发送至一个或多个主题。主题通常代表一类消息如日志、事件或其他数据类型。分区Kafka 主题可以被划分为多个分区每个分区是消息的物理存储单元。分区可以并行处理消息并且每个分区都有独立的偏移量offset来跟踪已消费的消息。分区策略用于确定消息将被发送至哪个分区的规则。Kafka 提供了多种分区策略包括轮询Round-robin、哈希Hashing和自定义分区策略。生产者可根据需求选择合适的分区策略。轮询分区策略轮询分区策略是最简单的策略它按顺序将消息发送至不同分区。这确保了消息在不同分区间的均匀分布适用于负载均衡场景。哈希分区策略哈希分区策略根据消息的键Key进行哈希计算将相同键的消息路由至相同分区。这保证了具有相同键的消息始终进入同一分区。自定义分区策略开发人员可以编写自定义分区策略根据特定业务逻辑将消息路由至分区。这使得消息路由更具灵活性。Producer APIKafka 为各种编程语言提供了生产者 API方便开发人员将消息发送至 Kafka 集群并可根据需求配置分区策略。生产者确认Kafka 生产者可以配置确认机制以确保消息成功写入分区。这包括确认acknowledgment机制生产者在等待分区确认后才会认为消息发送成功。消息分布消息将根据分区策略分布至不同分区生产者可以向不同分区发送消息以确保消息的分布和处理。 Kafka 生产端Producer在发送消息时需要考虑消息的分发策略。Kafka 生产端通过路由来将消息发送到与主题Topic关联的分区Partition从而实现高效的消息处理和数据分布。以下是一个使用 Java 实现 Kafka 生产端的路由和分配的示例 - 添加 Maven 依赖
dependency groupIdorg.apache.kafka/groupId artifactIdkafka-clients/artifactId version2.8.0/version
/dependency2. 创建 Kafka 生产者并配置参数 import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer; import java.util.Properties; public class KafkaProducerDemo { public static void main(String[] args) { // 配置生产者参数 Properties props new Properties(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, localhost:9092); props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());// 创建 Kafka 生产者实例 ProducerString, String producer new KafkaProducer(props);// 发送消息 for (int i 0; i 10; i) { String message Hello, Kafka! i; producer.send(new KeyValue(message, message)); }// 关闭生产者 producer.close(); }
}在上面的示例中我们创建了一个 Kafka 生产者并配置了 bootstrap.servers、key.serializer 和 value.serializer 等参数。生产者将消息发送到名为test-topic的主题该主题有两个分区Partition。 - 实现路由和分配
Kafka 生产端通过路由和分配策略来决定将消息发送到哪个分区。这可以通过实现自定义的 Partitioner 类来实现。以下是一个简单的示例将消息发送到分区序号小于等于消息序号的分区
import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.requests.SendResult; import java.util.List; public class CustomPartitioner implements Partitioner { Override public int partition(String topic, Object key, int numPartitions) { int partition (int) (key.hashCode() % numPartitions); if (partition 0) { partition 0; } return partition; }Override public void send(SendResult sendResult, ListObject records) { // 实现自定义发送逻辑例如记录发送结果 }
}4. 使用自定义分区器发送消息 在之前的生产者示例中我们将 Partitioner 类替换为自定义的 CustomPartitioner。然后将消息发送到与主题关联的分区 // 创建自定义分区器
CustomPartitioner partitioner new CustomPartitioner(); // 发送消息
for (int i 0; i 10; i) { String message Hello, Kafka! i; SendResult sendResult producer.send(new KeyValue(message, message), partitioner); System.out.printf(Message %s sent to partition %d with offset %d%n, message, sendResult.getPartition(), sendResult.getOffset());
}14、说说mysql索引为什么B树 平衡性B树是一种自平衡数据结构能保持树的高度相对较低。这意味着在最坏情况下查找特定条目的时间复杂度为 O(log n)其中 n 是索引中的条目数量。这对于实现高效检索操作至关重要。顺序访问性能B树的内部节点包含指向子节点的指针使 B树在范围查询中具有较高效率。例如如需查询某一范围内的数据B树可沿叶子节点顺序遍历从而提高顺序访问性能。磁盘读写性能B树的节点大小通常与数据库页大小相同有助于减少磁盘读写操作。较大节点可容纳更多键值对降低磁盘 I/O 频率。有序性B树的叶子节点形成有序链表便于实现范围查询和排序。数据库能快速遍历有序数据。范围查询优势得益于 B树的有序性范围查询和排序效率较高。可快速找到指定范围内的数据无需扫描整个表。支持多列索引B树索引支持多列组合索引有助于应对复杂查询条件。高扇出性能B树具有高扇出性能即每个内部节点拥有多个子节点。降低树高度减少磁盘读取次数。支持并发操作B树索引支持并发插入和删除操作适用于多用户、多线程的数据库环境。 15、说说主键索引二级索引 - 主键索引 a. 这是一种用于唯一标识每条记录的索引。每个表格仅能设立一个主键索引。 b. 主键索引通常用于加速检索特定记录或进行数据修改操作。 c. 主键索引要求索引列的值唯一且非空。 d. 主键索引作为表的聚集索引意味着数据按照主键索引的顺序进行物理存储。 e. 主键索引通常具有较高的查找效能因为它能快速定位到特定行。
- 二级索引 a. 二级索引是除主键索引以外的一种索引用于加速特定查询条件的查找。 b. 表可以有多个二级索引用于加速不同类型的查询如根据非主键列的条件检索数据。 c. 二级索引的值可以重复不要求唯一性因为它们是辅助索引主要用于快速定位主键值。 d. 二级索引通常包含索引列的值和对应的主键值以便在查找时可直接找到对应行。 e. 二级索引能提升查询性能但也会占用额外的存储空间和增加更新操作的开销。 16、说说mysql ACID 原子性Atomicity a. 原子性确保事务是不可分割的操作单元要么全部执行要么全部不执行。若事务的任何部分失败整个事务将回滚数据库状态恢复至初始状态。 b. 原子性旨在防止不完整或部分执行的事务确保数据库一致性。 一致性Consistency a. 一致性确保事务在执行前后保持数据库的一致性状态。即事务执行后数据库应从一个一致状态转变为另一个一致状态。 b. 一致性要求事务操作遵循数据库的完整性约束和业务规则维持数据合法性。 隔离性Isolation a. 隔离性确保并发执行的事务不会相互干扰每个事务都仿佛在无其他事务干扰的情况下执行。 b. 隔离性分为不同级别如读未提交、读已提交、可重复读和串行化以控制并发事务间的相互影响。 持久性Durability a. 持久性确保事务成功提交后其结果永久存储在数据库中即使系统崩溃或断电也不会丢失。 b. 数据库系统通常采用日志文件实现持久性以便在系统崩溃后恢复事务。 17、mysql事务隔离级别RR解决幻读吗什么场景下会幻读
- 什么是幻读 幻读又称不可重复读是一种并发事务问题。它发生在多个事务之间其中一个事务在某个范围内插入新行而另一个事务在此范围内尝试查询数据。这可能导致查询事务看到新插入的行即使在其开始查询之前这些行并不存在。幻读与脏读类似但关注的是插入操作而非修改操作。
- RR隔离级别如何解决幻读 RR 隔离级别通过使用锁或多版本并发控制MVCC来解决幻读问题。在 RR 隔离级别下事务会获取一个范围锁确保在事务进行中查询的范围内的数据在事务结束前不会被其他事务修改或插入。 例如如果事务 A 在 RR 隔离级别下查询某个范围的数据另一个事务 B 想要在相同范围内插入新行事务 B 将被阻塞直到事务 A 完成。这样可以防止事务 A 看到事务 B 插入的新行从而解决幻读问题。 可能出现幻读问题 假设一个在线购物系统多个用户同时浏览某个商品的库存情况。如果一个用户正在查询库存时另一个用户刚好购买了最后一件商品事务A可能在查询时看到商品的数量是1但在实际购买时库存已经为0了这就是幻读问题。 18、MVCC事务版本号怎么生成存在哪里 MVCC多版本并发控制是一种并发控制机制允许数据库系统在同一时间点存在多个版本的数据以支持事务隔离和并发查询。每个数据行在 MVCC 中都有一个或多个版本号用于标识数据的不同版本。版本号的生成和存储取决于数据库管理系统的具体实现。 通常MVCC系统中的版本号是在数据行上生成的并且通常包括以下信息 事务IDTransaction ID版本号通常包含生成该版本的事务的唯一标识符或 ID。这使得数据库能够跟踪哪个事务生成了哪个版本的数据。时间戳Timestamp版本号通常包括生成该版本的时间戳。时间戳可以是事务开始或提交的时间以及其他时间单位用于确定版本的时间顺序。 版本号的生成和存储方式因 DBMS 而异但通常存储在数据行的元数据中以便系统能够在查询时识别和访问不同版本的数据。数据库系统还维护一个版本控制的数据结构通常称为版本链或版本表以跟踪每个数据行的不同版本及其关系。 MVCC 的主要优点是它允许高度并发的读取操作因为每个事务都可以看到一致性的数据快照而不会阻塞其他事务的写入操作。不同数据库管理系统的 MVCC 实现方式可能有所不同但它们都旨在提供高并发性和事务隔离。在查询时数据库系统会根据当前事务的 ID 或时间戳选择适当版本的数据以确保事务之间的隔离。 19、说说binlogredologundolog
- Binlog二进制日志 a. binlog 是 MySQL 数据库中的二进制日志用于记录数据库的变更操作如插入、更新和删除。它以二进制形式记录了 SQL 语句或数据变动事件的日志而不是实际的数据值。 b. 主要用途在于数据库的备份、主从复制和故障恢复。通过分析 binlog可以还原数据库的历史状态。
- Redo Log重做日志 a. redo log 是数据库管理系统中的一种日志主要用于记录数据变动操作。它以物理方式记录了对数据库页的更改而非 SQL 语句。 b. 主要用途是确保事务的持久性Durability在数据库系统发生崩溃或故障时可以使用 redo log 来重放事务以确保数据的一致性。
- Undo Log撤销日志 a. undo log 也是数据库管理系统中的一种日志用于记录事务的撤销操作。它包含了事务执行前的数据状态以便在需要时回滚事务。 b. 主要用途是支持事务的回滚操作和多版本并发控制MVCC。在事务发生回滚时可以使用 undo log 将数据还原到之前的状态。 简单记忆 binlog 用于记录数据更改的逻辑日志通常用于备份和复制。redo log 用于记录物理数据页的更改以确保持久性。undo log 用于支持事务的回滚和多版本并发控制。 20、挂了用什么log主从同步用什么log 当数据库系统发生崩溃或非正常关闭时崩溃恢复日志通常是 redo log用于重放未完成的事务以确保数据的持久性。主从同步通常依赖于二进制日志Binary log来保持主数据库和从数据库之间的数据一致性以支持数据库复制和高可用性方案。 数据库管理中存在多种不同类型的日志各自用于不同的目的主要包括
- Crash Recovery Log崩溃恢复日志 用于在数据库系统发生崩溃或非正常关闭时恢复数据至一致状态。通常这包括数据库的 redo log用于重放未完成的事务以确保数据的持久性。
- Binary Log二进制日志或Binlog 用于记录数据库的修改操作如插入、更新和删除。它通常用于数据库备份、主从复制和数据库同步。
- Error Log错误日志 用于记录数据库系统的错误信息、警告和异常情况。这对于诊断和解决问题非常有帮助。
- Transaction Log事务日志 用于记录事务的操作以支持数据库的事务性和回滚操作。这包括数据库的 undo log它用于支持事务的回滚操作。 21、说说binlog的两阶段提交 两阶段提交Two-Phase Commit是分布式系统中的一种事务协议用于在多个节点上执行原子操作。 在两阶段提交中事务分为两个阶段预提交Pre-Commit和确认提交Commit。 以下是对两阶段提交的具体解释和 Java 实现。
- 预提交阶段 在这个阶段事务需要在所有参与者节点上执行并将执行结果存储在事务日志如 MySQL 的 binlog中。此时事务仍然可以被回滚Rollback。
- 确认提交阶段
在这个阶段事务已经完成在所有参与者节点上的执行并且日志已经被持久化。此时事务不能被回滚只能向前推进Commit或回滚Rollback。
以下是 Java 实现的两阶段提交代码示例
public class TwoPhaseCommit { private final Logger logger LoggerFactory.getLogger(TwoPhaseCommit.class);private final AtomicBoolean committed new AtomicBoolean(false);public void preCommit() { logger.info(Entering pre-commit stage);// 在这里执行事务操作如更新、插入等 // …logger.info(Finished pre-commit stage); }public void commit() { if (committed.getAndUpdate(true, x - true)) { logger.info(Entering commit stage);// 在这里执行提交操作如持久化日志、发送确认消息等 // …logger.info(Finished commit stage); } else { logger.warn(Commit failed); } }public void rollback() { if (committed.getAndUpdate(false, x - false)) { logger.info(Entering rollback stage);// 在这里执行回滚操作如撤销更新、删除日志等 // …logger.info(Finished rollback stage); } else { logger.warn(Rollback failed); } }
}在这个示例中我们使用了一个原子布尔变量 committed 来标记事务是否已经进入确认提交阶段。 在预提交阶段事务执行操作并将结果记录在日志中。 然后事务进入确认提交阶段执行持久化操作并发送确认消息。如果事务已经进入确认提交阶段那么不能再回滚事务。 使用这个两阶段提交框架可以确保事务在所有节点上的一致性和原子性。在实际应用中还需要考虑如何处理事务日志、异常处理、并发控制等问题。 22、算法题买卖股票 描述 给定一个数组 prices 它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择某一天买入这只股票并在未来的某一天卖出。 设计一个算法来计算你所能获得的最大利润。 返回你从这笔交易中能获得的最大利润。如果无法获得任何利润返回 0 。 思路 首先我们需要找到买入和卖出的最佳时机因此我们需要计算每个元素的价格差。接下来我们需要找到最大的价格差即最大利润。为了找到最大利润我们可以使用双指针法一个指针从左边开始另一个指针从右边开始比较左右两边的价格差更新最大利润。 实现 以下是 Java 代码实现 public class Main { public static void main(String[] args) { int[] prices {7, 1, 5, 3, 6, 4}; System.out.println(maxProfit(prices)); }public static int maxProfit(int[] prices) { int buy Integer.MIN_VALUE, sell Integer.MIN_VALUE; int maxProfit 0;for (int i 0; i prices.length; i) { int temp Math.max(buy, prices[i] - sell); buy Math.max(buy, temp); sell Math.min(sell, prices[i] - temp); maxProfit Math.max(maxProfit, sell - buy); }return maxProfit; }
}当输入 [7, 1, 5, 3, 6, 4] 时输出结果为 5表示从这笔交易中能获得的最大利润为 5。 尼恩说在最后 在尼恩的50读者社群中很多、很多小伙伴需要进大厂、拿高薪。 尼恩团队会持续结合一些大厂的面试真题给大家梳理一下学习路径看看大家需要学点啥 前面用多篇文章给大家介绍阿里、百度、字节、滴滴的真题 《炸裂靠“吹牛”过京东一面月薪40k》 《太猛了靠“吹牛”过顺丰一面月薪30K》 《问懵了…美团一面索命44问过了就60W》 《炸裂了…京东一面索命40问过了就50W》 《问麻了…阿里一面索命27问过了就60W》 《百度狂问3小时大厂offer到手小伙真狠》 《饿了么太狠面个高级Java抖这多硬活、狠活》 《字节狂问一小时小伙offer到手太狠了》 《收个滴滴Offer从小伙三面经历看看需要学点啥》 这些真题都会收入到 史上最全、持续升级的 PDF电子书 《尼恩Java面试宝典》。 本文收录于 《尼恩Java面试宝典》。 基本上把尼恩的 《尼恩Java面试宝典》吃透大厂offer很容易拿到滴。另外下一期的 大厂面经大家有啥需求可以发消息给尼恩。 尼恩技术圣经系列PDF 《NIO圣经一次穿透NIO、Selector、Epoll底层原理》《Docker圣经大白话说Docker底层原理6W字实现Docker自由》《K8S学习圣经大白话说K8S底层原理14W字实现K8S自由》《SpringCloud Alibaba 学习圣经10万字实现SpringCloud 自由》《大数据HBase学习圣经一本书实现HBase学习自由》《大数据Flink学习圣经一本书实现大数据Flink自由》《响应式圣经10W字实现Spring响应式编程自由》《Go学习圣经Go语言实现高并发CRUD业务开发》 ……完整版尼恩技术圣经PDF集群请找尼恩领取 《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF请到下面公号【技术自由圈】取↓↓↓
- 上一篇: 成都公司做网站多少钱wordpress插件不显示
- 下一篇: 成都好的网站建设公司网络营销ppt怎么做
相关文章
-
成都公司做网站多少钱wordpress插件不显示
成都公司做网站多少钱wordpress插件不显示
- 技术栈
- 2026年03月21日
-
成都公司网站做团购网站需要什么资质
成都公司网站做团购网站需要什么资质
- 技术栈
- 2026年03月21日
-
成都公司网站竞价推广的优势有哪些
成都公司网站竞价推广的优势有哪些
- 技术栈
- 2026年03月21日
-
成都好的网站建设公司网络营销ppt怎么做
成都好的网站建设公司网络营销ppt怎么做
- 技术栈
- 2026年03月21日
-
成都记者留言网站做网站好还是阿里巴巴
成都记者留言网站做网站好还是阿里巴巴
- 技术栈
- 2026年03月21日
-
成都家居网站建设月光博客 网站模板
成都家居网站建设月光博客 网站模板
- 技术栈
- 2026年03月21日






