网站建设多少钱 小江网页设计中小企业网站建设策划
2026/4/6 9:17:07 网站建设 项目流程
网站建设多少钱 小江网页设计,中小企业网站建设策划,企业网站404页面设计,网站架构设计师是做什么的阿里今年的校招薪资也在陆续开了。根据网上的爆料来看#xff0c;今年后端薪资大概是#xff1a;白菜 26K#xff0c;小 SP 27~28K#xff0c;大 SP 29~30K#xff0c;SSP 是 31~32K。阿里集团是 16 薪#xff0c;蚂蚁是 15 薪#xff0c;菜鸟是 14 薪。某些部门会有 2k…阿里今年的校招薪资也在陆续开了。根据网上的爆料来看今年后端薪资大概是白菜 26K小 SP 27~28K大 SP 29~30KSSP 是 31~32K。阿里集团是 16 薪蚂蚁是 15 薪菜鸟是 14 薪。某些部门会有 2k 房补目前了解到的是淘天应该有。这个薪资其实还蛮高的但和小红书等公司今年开的相比确实差点。现在还没大规模开所以到时候实际开的有可能会和这个有一点小出入个人预测白菜应该有 24k 和 25k 的。阿里的技术面试一般三轮或者两轮极少四轮技术面表现还不错的话就会约 HR 面。阿里的 HR 面懂得都懂需要重视不是到了 HR 面就比较稳了还有一点投递小技巧阿里不同的部门一般是可以分开投递的。阿里面试前几年大家感觉难度还比较大这几年各种常见的八股都问烂的认真准备一下整体上都不会有什么太大问题。阿里的技术面一般是问实习、项目和常见的八股一般一面更多的是问八股考察基础到了后面会问更多实习和项目相关的问题。那阿里的整体面试难度如何呢给大家分享一篇阿里淘天的秋招面经我精选了一二面中的一些比较典型的面试问题进行解答 大家可以感受一下美团的面试难度如何。概览介绍自己的项目作为求职者我们可以从哪些方案去准备项目经历的回答梳理项目全貌一句话概括项目用简洁的语言说清楚这个项目是做什么的核心业务/目标以及为什么要做项目背景、要解决什么痛点。核心功能与亮点介绍项目的主要功能模块特别是那些技术含量高或业务价值大的部分。技术架构与选型能清晰地说明项目的整体技术架构比如是微服务、单体用了哪些中间件并解释为什么选择这些技术技术选型的考量。准备好可能被要求画简要架构图或解释关键模块设计。明确你的角色与贡献你的角色清楚说明你在项目中担任的角色比如核心开发者、模块负责人、项目经理等。具体职责你具体负责了哪些模块或任务关键贡献重中之重用 STAR 法则 (Situation, Task, Action, Result) 来准备几个实际案例。重点突出你通过具体行动取得了可量化的成果或解决了关键问题一定要具体场景而非罗列技术。例如“负责优化 XX 接口通过 A、B、C 措施将响应时间从 X 降低到 Y提升了 Z% 的用户体验”。准备解决问题的亮点案例挖掘挑战回忆项目中遇到的最棘手的技术难题、性能瓶颈、或者复杂的业务逻辑实现。这个在面试中很可能会问到例如面试官会问你“面试中遇到了什么困难如何解决的”。展现思路详细说明你是如何分析问题用了什么工具怎么定位的、思考解决方案考虑了哪些方案为什么选择最终方案、最终如何解决的以及结果如何。提炼收获从解决这个问题的过程中你学到了什么技术上有什么成长或者对业务有了更深的理解深入理解关键技术吃透你在这个项目中用到的技术举个例子你的项目经历使用了 Seata 来做分布式事务那 Seata 相关的问题你要提前准备一下吧比如说 Seata 支持哪些配置中心、Seata 的事务分组是怎么做的、Seata 支持哪些事务模式怎么选择。库存扣减这里为什么要用 Redis Lua 脚本在库存扣减这个典型的高并发场景下我们使用 Redis Lua 脚本主要是为了保证操作的原子性从而从根本上避免超卖问题。正常的库存扣减逻辑是读库存-判断够不够-写回新库存。在高并发下两个线程可能同时读到库存都够结果一个库存卖了两次就超卖了。Lua 脚本能把这三步打包成一个命令在 Redis 服务端一次性执行完。因为 Redis 是单线程执行命令所以在跑这个脚本的期间不会有其他命令插进来这就保证了原子性。不过 Lua 脚本依然存在下面这些缺陷如果 Lua 脚本运行时出错并中途结束之后的操作不会进行但是之前已经发生的写操作不会撤销所以即使使用了 Lua 脚本也不能实现类似数据库回滚的原子性。Redis Cluster 下 Lua 脚本的原子操作无法保证原因是无法保证所有的 key 都在同一个hash slot哈希槽上。Redis 和 MySQL 一致性如何保证缓存和数据库一致性是个挺常见的技术挑战。引入缓存主要是为了提升性能、减轻数据库压力但确实会带来数据不一致的风险。绝对的一致性往往意味着更高的系统复杂度和性能开销所以实践中我们通常会根据业务场景选择合适的策略在性能和一致性之间找到一个平衡点。下面单独对Cache Aside Pattern旁路缓存模式来聊聊。这是非常常用的一种缓存读写策略它的读写逻辑是这样的读操作先尝试从缓存读取数据。如果缓存命中直接返回数据。如果缓存未命中从数据库查询数据将查到的数据放入缓存并返回数据。写操作先更新数据库。再直接删除缓存中对应的数据。图解如下如果更新数据库成功而删除缓存这一步失败的情况的话简单说有两个解决方案缓存失效时间TTL - Time To Live变短不推荐治标不治本我们让缓存数据的过期时间变短这样的话缓存就会从数据库中加载数据。另外这种解决办法对于先操作缓存后操作数据库的场景不适用。增加缓存更新重试机制常用如果缓存服务当前不可用导致缓存删除失败的话我们就隔一段时间进行重试重试次数可以自己定。不过这里更适合引入消息队列实现异步重试将删除缓存重试的消息投递到消息队列然后由专门的消费者来重试直到成功。虽然说多引入了一个消息队列但其整体带来的收益还是要更高一些。Redis 如何找到慢查询命令Redis 提供了一个内置的慢查询日志 (Slow Log)功能专门用来记录执行时间超过指定阈值的命令。这对于排查性能瓶颈、找出导致 Redis 阻塞的“慢”操作非常有帮助原理和 MySQL 的慢查询日志类似。在redis.conf文件中我们可以使用slowlog-log-slower-than参数设置耗时命令的阈值并使用slowlog-max-len参数设置耗时命令的最大记录条数。当 Redis 服务器检测到执行时间超过slowlog-log-slower-than阈值的命令时就会将该命令记录在慢查询日志slow log中这点和 MySQL 记录慢查询语句类似。当慢查询日志超过设定的最大记录条数之后Redis 会把最早的执行命令依次舍弃。⚠️ 注意由于慢查询日志会占用一定内存空间如果设置最大记录条数过大可能会导致内存占用过高的问题。slowlog-log-slower-than和slowlog-max-len的默认配置如下可以自行修改# The following time is expressed in microseconds, so 1000000 is equivalent # to one second. Note that a negative number disables the slow log, while # a value of zero forces the logging of every command. slowlog-log-slower-than 10000 # There is no limit to this length. Just be aware that it will consume memory. # You can reclaim memory used by the slow log with SLOWLOG RESET. slowlog-max-len 128除了修改配置文件之外你也可以直接通过CONFIG命令直接设置# 命令执行耗时超过 10000 微妙即10毫秒就会被记录 CONFIG SET slowlog-log-slower-than 10000 # 只保留最近 128 条耗时命令 CONFIG SET slowlog-max-len 128获取慢查询日志的内容很简单直接使用SLOWLOG GET命令即可。127.0.0.1:6379 SLOWLOG GET 1) 1) (integer) 5 2) (integer) 1684326682 3) (integer) 12000 4) 1) KEYS 2) * 5) 172.17.0.1:61152 6) // ...慢查询日志中的每个条目都由以下六个值组成唯一 ID: 日志条目的唯一标识符。时间戳 (Timestamp): 命令执行完成时的 Unix 时间戳。耗时 (Duration): 命令执行所花费的时间单位是微秒。命令及参数 (Command): 执行的具体命令及其参数数组。客户端信息 (Client IP:Port): 执行命令的客户端地址和端口。客户端名称 (Client Name): 如果客户端设置了名称 (CLIENT SETNAME)。SLOWLOG GET命令默认返回最近 10 条的的慢查询命令你也自己可以指定返回的慢查询命令的数量SLOWLOG GET N。下面是其他比较常用的慢查询相关的命令# 返回慢查询命令的数量 127.0.0.1:6379 SLOWLOG LEN (integer) 128 # 清空慢查询命令 127.0.0.1:6379 SLOWLOG RESET OK列举一些 Redis 中 O(n) 的命令Redis 中的大部分命令都是 O(1)时间复杂度但也有少部分 O(n) 时间复杂度的命令例如KEYS *会返回所有符合规则的 key。HGETALL会返回一个 Hash 中所有的键值对。LRANGE会返回 List 中指定范围内的元素。SMEMBERS返回 Set 中的所有元素。SINTER/SUNION/SDIFF计算多个 Set 的交集/并集/差集。……由于这些命令时间复杂度是 O(n)有时候也会全表扫描随着 n 的增大执行耗时也会越长从而导致客户端阻塞。不过 这些命令并不是一定不能使用但是需要明确 N 的值。另外有遍历的需求可以使用HSCAN、SSCAN、ZSCAN代替。缓存穿透和缓存击穿有什么区别如何解决缓存穿透中请求的 key 既不存在于缓存中也不存在于数据库中。缓存穿透缓存击穿中请求的 key 对应的是热点数据该数据存在于数据库中但不存在于缓存中通常是因为缓存中的那份数据已经过期。缓存击穿缓存穿透的常见解决方法缓存无效 key如果缓存和数据库都查不到某个 key 的数据就写一个到 Redis 中去并设置过期时间。布隆过滤器在缓存层之前加一层布隆过滤器把所有真实存在的 key例如所有商品 id、用户 id 等预热进去。接口限流 黑名单对单个 IP、UID、设备指纹等维度做限流如 1 秒最多 100 次触发限流阈值后加入临时/永久黑名单直接 403。限流的具体方案可以参考这篇文章服务限流详解[1]。缓存击穿的常见解决方法永不过期不推荐设置热点数据永不过期或者过期时间比较长。提前预热推荐针对热点数据提前预热将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。加锁看情况在缓存失效后通过设置互斥锁确保只有一个请求去查询数据库并更新缓存。遇到过 MySQL 慢查询问题吗怎么解决的为了优化慢 SQL 我们首先要找到哪些 SQL 语句执行速度比较慢。MySQL 慢查询日志是用来记录 MySQL 在执行命令中响应时间超过预设阈值的 SQL 语句。因此通过分析慢查询日志我们就可以找出执行速度比较慢的 SQL 语句。出于性能层面的考虑慢查询日志功能默认是关闭的你可以通过以下命令开启# 开启慢查询日志功能 SET GLOBAL slow_query_log ON; # 慢查询日志存放位置 SET GLOBAL slow_query_log_file /var/lib/mysql/ranking-list-slow.log; # 无论是否超时未被索引的记录也会记录下来。 SET GLOBAL log_queries_not_using_indexes ON; # 慢查询阈值秒SQL 执行超过这个阈值将被记录在日志中。 SET SESSION long_query_time 1; # 慢查询仅记录扫描行数大于此参数的 SQL SET SESSION min_examined_row_limit 100;设置成功之后使用show variables like slow%;命令进行查看。| Variable_name | Value | ----------------------------------------------------------- | slow_launch_time | 2 | | slow_query_log | ON | | slow_query_log_file | /var/lib/mysql/ranking-list-slow.log | ----------------------------------------------------------- 3 rows in set (0.01 sec)我们故意在百万数据量的表(未使用索引)中执行一条排序的语句SELECT score,name FROM cus_order ORDER BY score DESC;确保自己有对应目录的访问权限chmod 755 /var/lib/mysql/查看对应的慢查询日志cat /var/lib/mysql/ranking-list-slow.log我们刚刚故意执行的 SQL 语句已经被慢查询日志记录了下来# Time: 2022-10-09T08:55:37.486797Z # UserHost: root[root] [172.17.0.1] Id: 14 # Query_time: 0.978054 Lock_time: 0.000164 Rows_sent: 999999 Rows_examined: 1999998 SET timestamp1665305736; SELECT score,name FROM cus_order ORDER BY score DESC;这里对日志中的一些信息进行说明Time被日志记录的代码在服务器上的运行时间。UserHost谁执行的这段代码。Query_time这段代码运行时长。Lock_time执行这段代码时锁定了多久。Rows_sent慢查询返回的记录。Rows_examined慢查询扫描过的行数。实际项目中慢查询日志通常会比较复杂我们需要借助一些工具对其进行分析。像 MySQL 内置的mysqldumpslow工具就可以把相同的 SQL 归为一类并统计出归类项的执行次数和每次执行的耗时等一系列对应的情况。找到了慢 SQL 之后我们可以通过EXPLAIN命令分析对应的SELECT语句mysql EXPLAIN SELECTscore,nameFROMcus_orderORDERBYscoreDESC; -------------------------------------------------------------------------------------------------------------------- | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | -------------------------------------------------------------------------------------------------------------------- | 1 | SIMPLE | cus_order | NULL | ALL | NULL | NULL | NULL | NULL | 997572 | 100.00 | Using filesort | -------------------------------------------------------------------------------------------------------------------- 1 row in set, 1warning (0.00 sec)比较重要的字段说明select_type查询的类型常用的取值有 SIMPLE普通查询即没有联合查询、子查询、PRIMARY主查询、UNIONUNION 中后面的查询、SUBQUERY子查询等。table表示查询涉及的表或衍生表。type执行方式判断查询是否高效的重要参考指标结果值从差到好依次是ALL index range ~ index_merge ref eq_ref const system。rows: SQL 要查找到结果集需要扫描读取的数据行数原则上 rows 越少越好。......什么是反射应用场景是简单来说Java 反射 (Reflection) 是一种在程序运行时动态地获取类的信息并操作类或对象方法、属性的能力。通常情况下我们写的代码在编译时类型就已经确定了要调用哪个方法、访问哪个字段都是明确的。但反射允许我们在运行时才去探知一个类有哪些方法、哪些属性、它的构造函数是怎样的甚至可以动态地创建对象、调用方法或修改属性哪怕这些方法或属性是私有的。正是这种在运行时“反观自身”并进行操作的能力使得反射成为许多通用框架和库的基石。它让代码更加灵活能够处理在编译时未知的类型。我们平时写业务代码可能很少直接跟 Java 的反射Reflection打交道。但你可能没意识到你天天都在享受反射带来的便利很多流行的框架比如 Spring/Spring Boot、MyBatis 等底层都大量运用了反射机制这才让它们能够那么灵活和强大。下面简单列举几个最场景的场景帮助大家理解。1.依赖注入与控制反转IoC以 Spring/Spring Boot 为代表的 IoC 框架会在启动时扫描带有特定注解如Component,Service,Repository,Controller的类利用反射实例化对象Bean并通过反射注入依赖如Autowired、构造器注入等。2.注解处理注解本身只是个“标记”得有人去读这个标记才知道要做什么。反射就是那个“读取器”。框架通过反射检查类、方法、字段上有没有特定的注解然后根据注解信息执行相应的逻辑。比如看到Value就用反射读取注解内容去配置文件找对应的值再用反射把值设置给字段。3.动态代理与 AOP想在调用某个方法前后自动加点料比如打日志、开事务、做权限检查AOP面向切面编程就是干这个的而动态代理是实现 AOP 的常用手段。JDK 自带的动态代理Proxy 和 InvocationHandler就离不开反射。代理对象在内部调用真实对象的方法时就是通过反射的Method.invoke来完成的。public class DebugInvocationHandler implements InvocationHandler { privatefinal Object target; // 真实对象 public DebugInvocationHandler(Object target) { this.target target; } // proxy: 代理对象, method: 被调用的方法, args: 方法参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(切面逻辑调用方法 method.getName() 之前); // 通过反射调用真实对象的同名方法 Object result method.invoke(target, args); System.out.println(切面逻辑调用方法 method.getName() 之后); return result; } }4.对象关系映射ORM像 MyBatis、Hibernate 这种框架能帮你把数据库查出来的一行行数据自动变成一个个 Java 对象。它是怎么知道数据库字段对应哪个 Java 属性的还是靠反射。它通过反射获取 Java 类的属性列表然后把查询结果按名字或配置对应起来再用反射调用 setter 或直接修改字段值。反过来保存对象到数据库时也是用反射读取属性值来拼 SQL。WebSocket 与短轮询、长轮询的区别这三种方式都是为了解决“客户端如何及时获取服务器最新数据实现实时更新”的问题。它们的实现方式和效率、实时性差异较大。1.短轮询Short Polling原理客户端每隔固定时间如 5 秒发起一次 HTTP 请求询问服务器是否有新数据。服务器收到请求后立即响应。优点实现简单兼容性好直接用常规 HTTP 请求即可。缺点实时性一般消息可能在两次轮询间到达用户需等到下次请求才知晓。资源浪费大反复建立/关闭连接且大多数请求收到的都是“无新消息”极大增加服务器和网络压力。2.长轮询Long Polling原理客户端发起请求后若服务器暂时无新数据则会保持连接直到有新数据或超时才响应。客户端收到响应后立即发起下一次请求实现“伪实时”。优点实时性较好一旦有新数据可立即推送无需等待下次定时请求。空响应减少减少了无效的空响应提升了效率。缺点服务器资源占用高需长时间维护大量连接消耗服务器线程/连接数。资源浪费大每次响应后仍需重新建立连接且依然基于 HTTP 单向请求-响应机制。3. WebSocket原理客户端与服务器通过一次 HTTP Upgrade 握手后建立一条持久的 TCP 连接。之后双方可以随时、主动地发送数据实现真正的全双工、低延迟通信。优点实时性强数据可即时双向收发延迟极低。资源效率高连接持续无需反复建立/关闭减少资源消耗。功能强大支持服务端主动推送消息、客户端主动发起通信。缺点使用限制需要服务器和客户端都支持 WebSocket 协议。对连接管理有一定要求如心跳保活、断线重连等。实现麻烦实现起来比短轮询和长轮询要更麻烦一些。Websocket 示意图SSE 与 WebSocket 有什么区别SSE (Server-Sent Events) 和 WebSocket 都是用来实现服务器向浏览器实时推送消息的技术让网页内容能自动更新而不需要用户手动刷新。虽然目标相似但它们在工作方式和适用场景上有几个关键区别通信方式:SSE:单向通信。只有服务器能向客户端浏览器发送数据。客户端不能通过同一个连接向服务器发送数据需要发起新的 HTTP 请求。WebSocket:**双向通信 (全双工)**。客户端和服务器可以随时互相发送消息实现真正的实时交互。底层协议:SSE:基于标准的 HTTP/HTTPS 协议。它本质上是一个“长连接”的 HTTP 请求服务器保持连接打开并持续发送事件流。不需要特殊的服务器或协议支持现有的 HTTP 基础设施就能用。WebSocket:使用独立的 ws:// 或 wss:// 协议。它需要通过一个特定的 HTTP Upgrade 请求来建立连接并且服务器需要明确支持 WebSocket 协议来处理连接和消息帧。实现复杂度和成本:SSE:实现相对简单主要在服务器端处理。浏览器端有标准的 EventSource API使用方便。开发和维护成本较低。WebSocket:稍微复杂一些。需要服务器端专门处理 WebSocket 连接和协议客户端也需要使用 WebSocket API。如果需要考虑兼容性、心跳、重连等开发成本会更高。断线重连:SSE:浏览器原生支持。EventSource API 提供了自动断线重连的机制。WebSocket:需要手动实现。开发者需要自己编写逻辑来检测断线并进行重连尝试。数据类型:SSE:主要设计用来传输文本(UTF-8 编码)。如果需要传输二进制数据需要先进行 Base64 等编码转换成文本。WebSocket:原生支持传输文本和二进制数据无需额外编码。为了提供更好的用户体验和利用其简单、高效、基于标准 HTTP 的特性Server-Sent Events (SSE) 是目前大型语言模型 API如 OpenAI、DeepSeek 等实现流式响应的常用甚至可以说是标准的技木选择。这里以 DeepSeek 为例我们发送一个请求并打开浏览器控制台验证一下可以看到响应头应里包含了text/event-stream说明使用的确实是 SSE。并且响应数据也确实是持续分块传输。TCP/IP 四层模型TCP/IP 四层模型是目前被广泛采用的一种模型,我们可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本由以下 4 层组成应用层传输层网络层网络接口层需要注意的是我们并不能将 TCP/IP 四层模型 和 OSI 七层模型完全精确地匹配起来不过可以简单将两者对应起来如下图所示TCP/IP 四层模型关于每一层作用的详细介绍请看 OSI 和 TCP/IP 网络分层模型详解基础[2] 这篇文章。为什么网络要分层说到分层我们先从我们平时使用框架开发一个后台程序来说我们往往会按照每一层做不同的事情的原则将系统分为三层复杂的系统分层会更多:Repository数据库操作Service业务操作Controller前后端数据交互复杂的系统需要分层因为每一层都需要专注于一类事情。网络分层的原因也是一样每一层只专注于做一类事情。好了再来说回“为什么网络要分层”。我觉得主要有 3 方面的原因各层之间相互独立各层之间相互独立各层之间不需要关心其他层是如何实现的只需要知道自己如何调用下层提供好的功能就可以了可以简单理解为接口调用。这个和我们对开发时系统进行分层是一个道理。提高了灵活性和可替换性每一层都可以使用最适合的技术来实现你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。并且每一层都可以根据需要进行修改或替换而不会影响到整个网络的结构。这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。大问题化小分层可以将复杂的网络问题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计实现和标准化。这个和我们平时开发的时候一般会将系统功能分解然后将复杂的问题分解为容易理解的更小的问题是相对应的这些较小的问题具有更好的边界目标和接口定义。我想到了计算机世界非常非常有名的一句话这里分享一下计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决计算机整个体系从上到下都是按照严格的层次结构设计的。TCP 和 UDP 区别特性TCPUDP连接性面向连接无连接可靠性可靠不可靠 (尽力而为)状态维护有状态无状态传输效率较低较高传输形式面向字节流面向数据报 (报文)头部开销20 - 60 字节8 字节通信模式点对点 (单播)单播、多播、广播常见应用HTTP/HTTPS, FTP, SMTP, SSHDNS, DHCP, SNMP, TFTP, VoIP, 视频流HTTP 和 HTTPS 有什么区别重要HTTP 和 HTTPS 对比端口号HTTP 默认是 80HTTPS 默认是 443。URL 前缀HTTP 的 URL 前缀是http://HTTPS 的 URL 前缀是https://。安全性和资源消耗HTTP 协议运行在 TCP 之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS 高但是 HTTPS 比 HTTP 耗费更多服务器资源。SEO搜索引擎优化搜索引擎通常会更青睐使用 HTTPS 协议的网站因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示从而对 SEO 产生影响。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询