Redis 相关面试题整理 更新中 

你的项目的哪些场景使用了 redis 如果发生了缓存击穿、穿透、雪崩如何解决 redis 作为缓存, mysql的数据如何与redis进行同步? 先介绍业务,看看业务符合什么场景 一致性较高场景 双写一致 读 写 | 延迟双删 分布式锁 读多写少 共享锁 排它锁 允许延迟一致 介绍一下你的异步方案 允许延时一致的业务,采用异步通知 MQ消息中间件 Canal中间件 强一致性(Redisson读写锁) 共享锁 阻塞写操作 排它锁 阻塞读和写操作 Redis作为缓存,数据的持久化是怎么做的? RDB save bgsave AOF RDB 的执行原理? fork主进程得到子进程 子进程共享主进程的内存数据(复制页表) copy-on-write AOF 的执行原理 配置项 always everysec no 重写触发 bgrewriteaof RDB 和 AOF 对比 持久化方式 数据完整性 文件大小 宕机恢复速度 数据恢复优先级 系统资源占用 使用场景 redis 的key过期了会立即删除吗 惰性删除 定期删除 SLOW(10hz) FAST Redis的过期策略:惰性删除+定期删除 配合使用 Redis 数据淘汰策略 noeviction volatile-ttl allkeys-random volatile-random allkeys-lru volatile-lru allkeys-lfu volatile-lfu 数据库有1000万数据,redis只能缓存20万,如何保证redis中的数据都是热点数据? 使用 allkeys-lru ...

2026-07-15 12:46:10 AM · 1 分钟

Vue 相关面试题整理 更新中 

从互联网整理而来 一、JS/TS 前置基础 var、let、const 区别 原型、原型链原理 闭包概念、使用场景、内存泄漏风险 同步异步、宏任务微任务执行顺序 Promise 三种状态、链式调用、静态方法 async/await 底层原理 数组常用遍历方法差异 深浅拷贝实现与区别 Object.defineProperty 与 Proxy 对比 Reflect 对象作用 箭头函数与普通函数区别 解构赋值、展开运算符 ES6 模块 import/export 与 CommonJS 区别 TypeScript 泛型、接口、类型推导 EventLoop 完整执行流程 二、Vue2 基础核心 Vue 双向绑定底层原理 Object.defineProperty 如何监听对象、数组变化 Vue2 数组重写了哪些方法,为什么不能监听下标修改 Dep、Watcher、Observer 三者关系 什么是响应式依赖收集、派发更新 数据劫持流程完整过程 computed 和 watch 区别 computed 缓存实现原理 methods、computed、watch 使用场景区分 Vue 生命周期全部钩子及执行时机 created、mounted、updated、destroyed 使用场景 父子组件生命周期执行顺序 v-if 和 v-show 底层区别与性能差异 v-for 绑定 key 的作用,key 不能用 index 的原因 v-if 和 v-for 同时使用的优先级与问题 v-model 底层语法糖实现 修饰符 .lazy .number .trim 原理 指令自定义实现,钩子函数有哪些 过滤器 filter 使用场景,Vue3 废弃原因 插值表达式、v-text、v-html 区别 Vue 模板编译流程 render 函数与 template 关系 VNode 虚拟 DOM 结构作用 Diff 算法执行流程 Vue2 Diff 同层比较、key 作用、头尾指针优化 patch 函数更新逻辑 nextTick 原理,微任务/宏任务降级策略 $nextTick 使用场景 三、Vue2 组件通信 父子组件 props 传递规则,单向数据流 props 类型校验、默认值、必填配置 $emit 子传父实现 .sync 修饰符作用,Vue3 移除原因 $parent、$children、$refs 获取组件/元素 provide / inject 使用场景与响应式缺陷 EventBus 事件总线实现、内存泄漏问题 Vuex 全局状态通信完整流程 $attrs、$listeners 跨层级透传 跨页面、多层级组件通信方案对比 四、Vuex 状态管理 Vuex 五大核心概念 state、getters、mutations、actions、modules mutations 必须同步、actions 异步原因 commit 和 dispatch 区别 getters 缓存特性 modules 模块划分,命名空间 namespaced 辅助函数 mapState/mapGetters/mapMutations/mapActions 使用 Vuex 持久化存储方案 Vuex 严格模式 strict 作用 多个组件同时修改同一 state 数据流 Vuex 底层响应式原理 五、Vue Router 2/3 SPA 单页面路由实现原理 hash 模式与 history 模式底层区别 history 模式后端 nginx 配置问题 路由导航守卫分类:全局、路由独享、组件内 导航守卫执行完整顺序 $route 和 $router 区别 路由传参 params 和 query 差异 params 刷新丢失参数解决方案 动态路由匹配、路由嵌套 路由懒加载实现与分包 addRoutes、addRoute 动态添加路由 路由元信息 meta 使用场景 路由缓存 keep-alive 原理 include/exclude/max 参数作用 activated、deactivated 生命周期钩子 路由跳转 push、replace、go 区别 登录鉴权全局路由拦截实现 六、Vue2 进阶知识点 keep-alive 缓存组件底层逻辑 异步组件、组件懒加载 组件递归实现菜单、树形结构 $once、$off、$on 事件方法 插槽分类:默认插槽、具名插槽、作用域插槽 作用域插槽数据传递原理 v-once 指令作用 Vue 模板编译生成 AST 抽象语法树 异步更新队列机制 页面大量数据渲染卡顿优化方案 Object.freeze 冻结数据对响应式的影响 $set 原理,什么场景必须使用 Vue2 响应式存在的缺陷 全局过滤器、全局指令、全局组件注册 mixin 混入原理、合并规则、冲突问题 七、Vue3 核心升级(Composition API) Vue3 相比 Vue2 性能提升点 Vue3 响应式改用 Proxy 优势 Proxy 对比 Object.defineProperty 解决了哪些痛点 Reflect 配合 Proxy 的作用 reactive、ref 区别与底层实现 ref 为什么基础类型需要包裹对象 toRef、toRefs 使用场景,解决的问题 computed 在 setup 中使用方式 watch、watchEffect 区别 watch 监听对象、数组深度监听配置 setup 执行时机,this 指向问题 setup 参数 props、context 内容 Composition API 对比 Options API 优势 script setup 语法糖带来的变化 script setup 中 defineProps、defineEmits、defineExpose 生命周期钩子组合式写法 onMounted/onUpdated 等 getCurrentInstance 获取组件实例 provide / inject 在 Vue3 中如何实现响应式 自定义 hooks 封装思路,复用逻辑 Vue3 生命周期完整列表,与 Vue2 对应关系 八、Vue3 模板、编译、Diff 优化 Vue3 模板编译优化:PatchFlags 标记 静态提升原理,减少 VNode 创建开销 缓存内联事件处理函数 Vue3 Diff 算法优化:最长递增子序列 Diff 对比流程相比 Vue2 改进点 Fragment 根节点多标签支持原理 Teleport 传送门组件底层实现 Suspense 异步组件加载处理 v-model 在 Vue3 语法变更,多 v-model 实现 .v-model 修饰符自定义处理 插槽 v-slot 简写语法变化 Vue3 移除 filter 过滤器替代方案 九、Pinia(Vue3 状态管理) Pinia 相比 Vuex 的优势 Pinia 核心概念 state、getters、actions Pinia 支持同步异步,不再区分 mutations defineStore 定义仓库,id 作用 直接修改 state 与 $patch 批量更新区别 $reset、$subscribe、$onAction 使用场景 Pinia 模块化拆分,无需命名空间 Pinia 持久化插件使用 setup 语法下使用 Pinia 多个仓库互相调用数据方法 十、Vue Router 4(Vue3) createRouter、createWebHashHistory、createWebHistory RouterView、RouterLink v-slot 插槽用法 useRoute、useRouter 组合式 API 获取路由实例 动态路由 addRoute 替换 addRoutes 路由守卫组合式写法 路由缓存与 Suspense 配合 路由元类型 TS 类型提示处理 十一、Vue3 高级特性 watchPostEffect、watchSyncEffect 区别 shallowRef、shallowReactive 浅层响应式作用 readonly、shallowReadonly 只读代理 customRef 自定义响应式引用 effectScope 作用域收集副作用 defineCustomElement 构建原生 webComponent Vue3 全局 API 变更 createApp 替代 new Vue() app.config 全局配置项 全局组件、指令、插件注册方式变化 Transition、TransitionGroup 动画组件原理 v-memo 缓存 VNode 优化渲染 异步 setup 函数配合 Suspense 十二、工程化 & 构建工具 Vue CLI 与 Vite 底层构建区别 Vite 冷启动快的原理,esbuild 预构建 Vite 热更新 HMR 实现机制 vite.config.js 常用配置 webpack 打包 Vue 文件流程 vue-loader .vue SFC 单文件组件解析过程 scoped 样式隔离原理,深度选择器 /deep/ ::v-deep :deep() CSS Module 使用方式 环境变量 .env 文件区分开发测试生产 跨域代理 proxy 配置 打包体积优化方案 分包、懒加载、gzip 压缩配置 TS 在 Vue 项目中配置声明文件 第三方 UI 库按需引入配置 全局自动导入组件、API 插件 unplugin-auto-import 十三、网络请求与封装 axios 拦截器请求、响应封装思路 请求 loading、统一错误处理封装 token 过期自动刷新逻辑 请求取消、重复请求拦截方案 并发请求处理 接口数据统一格式化处理 封装请求 hooks 适配 Vue3 十四、性能优化专项 减少不必要组件渲染手段 v-once、v-memo 使用场景 长列表虚拟滚动实现原理 响应式数据避免不必要监听 computed 缓存减少重复计算 图片懒加载方案 路由懒加载分包优化 keep-alive 合理缓存减少重复请求 避免频繁触发 watch 大列表数据冻结 Object.freeze 减少 DOM 操作,合理使用虚拟 DOM 打包体积优化:Tree-Shaking、剔除无用依赖 Vite/Webpack 构建速度优化 内存泄漏常见场景:定时器、事件监听、未销毁订阅 Chrome Performance 面板排查页面卡顿 十五、混合、插件、拓展开发 Vue2 mixin 缺陷,Vue3 用 hooks 替代原因 Vue 插件开发完整结构 install 方法 全局自定义指令完整开发 封装业务通用组件规范 二次封装 Element Plus / Ant Design Vue 封装全局弹窗、消息提示组件 自定义全局权限指令 v-permission 页面权限、按钮权限实现方案 全局错误捕获 errorHandler 埋点、全局请求监控插件封装 十六、项目实战场景问答题 项目整体架构分层设计 Vue2 升级 Vue3 迁移改造遇到的问题 大型项目状态管理选型 Vuex / Pinia 理由 复杂树形菜单、表格组件封装思路 表单校验全局统一封装方案 页面权限控制完整实现流程 多环境配置、多渠道打包处理 首屏加载速度优化做了哪些处理 路由鉴权、未登录拦截逻辑 列表大量数据渲染卡顿如何解决 项目打包体积过大优化方案 页面缓存、返回保留表单状态实现 接口并发冲突、重复提交拦截 移动端适配方案 vw/vh、rem 线上报错监控、异常捕获方案

2026-07-15 12:46:10 AM · 3 分钟

微信小程序 相关面试题整理 更新中 

从互联网整理而来 一、基础概念与运行机制 小程序与H5、App的核心区别 小程序双线程模型分别是什么,各自职责 逻辑层与视图层通信方式 小程序渲染流程完整过程 小程序启动流程(冷启动、热启动) 冷启动和热启动的差异 小程序分包加载机制概念 主包与分包限制规则 独立分包和普通分包区别 小程序的生命周期分类(应用、页面、组件) 小程序页面栈规则,最多存放多少页面 小程序登录流程整体逻辑 微信授权两种类型区别(基础授权、隐私授权) 小程序原生宿主环境提供哪些能力 小程序更新机制,静默更新与主动更新 二、文件结构与配置 小程序四种核心文件作用(json/wxml/wxss/js) app.json 全局配置常用字段 page.json 页面配置优先级与app.json关系 sitemap.json 作用 project.config.json 用途 app.js 全局App实例生命周期 页面js Page构造器生命周期 组件js Component构造器生命周期 usingComponents 引入组件配置 全局样式app.wxss和页面wxss权重规则 wxss与css差异,特有特性 rpx单位换算规则,适配原理 小程序支持的选择器有哪些,不支持哪些 图片、静态资源本地与线上引入规则 分包配置subpackages字段参数含义 三、WXML 模板语法 WXML数据绑定语法规则 插值表达式支持哪些运算 wx:if、wx:elif、wx:else 条件渲染 hidden属性与wx:if性能差异 wx:for列表渲染,wx:key作用 wx:key使用规范,禁止index的场景 block标签作用,是否生成真实节点 模板template定义与引入,数据传递 wxs脚本作用,运行环境限制 wxs与js的区别,能否调用小程序API 事件绑定bind、catch、capture-bind区别 mut-bind互斥事件作用 事件传参几种实现方式 数据双向绑定model语法 标签属性布尔值绑定规则 四、组件系统(原生+自定义组件) 小程序自定义组件创建完整结构 Component中properties传参配置规则 properties三种数据监听方式 data、properties、observers执行顺序 observers监听对象、数组深层变化写法 组件生命周期完整钩子 lifetimes与pageLifetimes区别 组件插槽slot,具名插槽使用 组件父子通信方式 triggerEvent触发自定义事件传参 selectComponent、selectAllComponents获取子组件 behaviors复用逻辑,合并规则 原生内置常用容器、表单、媒体组件 scroll-view滚动注意事项 movable-area、movable-view实现拖拽原理 canvas新旧版本差异,2d画布使用 web-view嵌入H5通信方案 cover-view、cover-image使用限制场景 自定义组件样式隔离options配置 组件pureDataPattern作用 五、数据管理与渲染更新 setData底层更新原理 setData频繁调用性能问题 setData单次数据大小限制 局部更新数据简写写法 直接修改this.data不调用setData为什么不更新视图 复杂对象、数组更新setData写法 全局数据共享几种方案 getApp()全局变量优缺点 globalData跨页面同步更新缺陷 数据本地持久化storage存储限制 wx.setStorage同步异步API区别 storage大数据存储优化方案 页面间数据传递方式对比 页面栈取上一页实例方法 大数据列表渲染卡顿优化思路 六、路由与页面跳转 五种路由API区别(navigateTo/redirectTo/reLaunch/switchTab/navigateBack) switchTab跳转限制条件 navigateTo无法跳tab页面解决方案 路由传参两种方式,长参数丢失问题 页面返回监听onUnload、onShow触发时机 获取当前页面栈方法getCurrentPages() 路由拦截统一封装思路 tabBar配置规则,自定义tabBar实现 自定义tabBar踩坑点 页面跳转后保留表单状态方案 七、网络请求与后端交互 wx.request请求基础配置 request合法域名校验规则,开发环境规避 小程序请求携带cookie机制 请求header统一封装token思路 拦截器封装wx.request方案 并发请求、请求超时处理 文件上传wx.uploadFile参数配置 文件下载wx.downloadFile使用场景 websocket实时通信完整流程 socket断线重连实现逻辑 接口返回加密数据解密处理 批量请求统一捕获异常 小程序不支持跨域的根本原因 上传图片压缩、裁剪处理 上传进度监听API 八、登录、授权、用户信息 wx.login获取code作用 code换取openid完整流程 openid、unionid区别与生成规则 隐私保护新规下获取用户头像昵称方案 getUserInfo接口废弃替代方案 手机号一键登录流程 授权scope各权限含义 用户拒绝授权后重新引导授权逻辑 登录态session_key过期处理 第三方登录、关联账号实现 登录状态持久化存储方案 多端打通unionid获取条件 隐私协议弹窗实现规范 小程序订阅消息下发流程 模板消息与订阅消息区别 九、媒体、图片、地图、设备API wx.chooseMedia选择图片视频参数 图片预览wx.previewImage使用 图片本地缓存方案 录音、播放音频API使用 video视频播放常见问题 map地图组件标记、覆盖物绘制 获取当前定位wx.getLocation权限配置 后台持续定位配置要求 设备信息、系统API获取 振动、剪贴板、屏幕亮度API 扫码wx.scanCode场景 蓝牙BLE设备连接流程 NFC基础使用场景 相机camera组件适配 文件管理FileSystemManager读写文件 十、性能优化专项 setData性能优化手段 长列表渲染优化方案 虚拟列表实现思路 分包加载优化首屏速度 图片懒加载处理 减少页面、组件层级嵌套 wxss样式体积压缩优化 分包预加载preloadRule配置 避免频繁创建定时器、监听事件 页面卸载清除所有订阅、定时器 包体积超限优化方案 开发者工具性能面板排查卡顿 避免在onShow频繁请求接口 图片资源压缩、webp适配 减少observers深层监听开销 十一、适配、兼容、多端 rpx、px、rem转换关系 刘海屏、安全区适配css写法 深色模式适配配置 不同微信版本API兼容处理 caniuse判断接口是否可用 小程序转H5、转uni-app差异 平板、PC端小程序适配要点 低版本微信兼容降级方案 字体、图片多设备适配 自定义导航栏适配胶囊按钮 十二、工程化、第三方框架 原生小程序、uni-app、Taro区别 Taro编译原理,多端适配逻辑 uni-app分包、条件编译写法 小程序npm依赖使用规则 按需引入UI组件库优化 工程化打包、环境变量区分 多环境请求域名配置 ESLint校验小程序代码规范 Git协同开发规范 CI自动上传小程序工具 十三、支付、分享、广告、业务能力 小程序支付完整流程 支付回调后端处理逻辑 分享onShareAppMessage、onShareTimeline配置 分享图、分享路径动态处理 分享到朋友圈限制条件 插屏广告、激励视频广告接入 小程序跳转其他小程序API 跳转限制与关联配置要求 客服消息接入流程 商品卡片、搜索收录配置sitemap 十四、安全、审核、合规 小程序合法域名、业务域名、web-view域名区别 前端存储敏感信息安全风险 session_key不能传输到前端原因 接口数据防篡改简单方案 隐私合规要求有哪些 图片、内容审核API调用 小程序常见审核驳回原因 诱导分享、诱导支付违规点 本地存储数据加密思路 防止恶意刷接口方案 十五、实战场景综合题 项目整体目录架构设计 封装通用请求库完整思路 全局登录拦截、未登录跳转实现 大型表单组件封装与校验 多页面共享登录状态管理 列表上拉加载、下拉刷新封装 图片上传、预览、删除完整流程 分包改造解决主包体积超限 页面返回保留搜索条件、分页数据 小程序热更新主动检测逻辑 websocket聊天断线重连方案 自定义tabBar遇到的坑与解决 页面大量数据滑动卡顿优化 线上白屏、加载失败排查思路 原生小程序迁移Taro/uni改造方案

2026-07-15 12:46:10 AM · 2 分钟

线性探测与链地址法的剖析

为什么我们需要两种冲突解决策略? 哈希表的核心矛盾在于:哈希函数将无限的定义域映射到有限的地址空间。根据鸽巢原理(Pigeonhole Principle),冲突是必然的。于是,计算机科学家们在"时间换空间“和”空间换时间“的永恒博弈中,诞生了两大流派: 开放定址法(Open Addressing):所有元素都存储在数组本身,冲突时寻找其他空位——原地消化。 链地址法(Separate Chaining):数组存储指针,冲突的元素在数组外形成链表——外部延展。 这两者看似只是实现细节的差异,实则反映了对内存模型、缓存行为、并发控制、最坏情况保证等底层哲学的不同理解。 一、线性探测(Linear Probing):极简主义的得与失 1.1 算法精要 线性探测的规则极其简单: 插入: h(k), h(k)+1, h(k)+2, ... (mod m) 查找: 同插入序列,直到找到或遇到空位 删除: 标记为"墓碑"(DELETED),不能物理清空 关键洞察:线性探测的查找路径是确定性的,这意味着它拥有完美的CPU缓存预取特性(Prefetching),在现代CPU架构下,连续内存访问的速度比指针跳转快一个数量级。 1.2 主聚集(Primary Clustering)的数学本质 这是线性探测最致命的缺陷,也是理解其性能天花板的钥匙。 假设负载因子为 α(α = n/m),当插入一个新元素时,它在某个位置发生冲突的概率不是简单的 α,而是该位置所在的连续占用块的长度占比。这个正反馈机制导致: 一旦形成长度为 L 的连续占用块,新元素落入该块的概率为 L/m 落入后,块长度变为 L+1,进一步增加未来冲突概率 最终导致占用块像雪崩一样快速增长 数学结论(Knuth 的经典分析): 成功查找的平均探测次数 ≈ 0.5 * (1 + 1/(1-α)) 插入的平均探测次数 ≈ 0.5 * (1 + 1/(1-α)^2) 当 α = 0.9 时,插入需要平均约 50.5 次探测,性能崩溃。这也是为什么线性探测要求负载因子严格控制在 0.7 以下。 1.3 删除与墓碑的隐藏代价 线性探测的删除必须使用墓碑,这带来三重悲剧: 空间污染:墓碑占用的位置无法被新数据直接覆盖(需要判断是否允许覆盖,复杂化逻辑) 查询退化:大量的墓碑会导致查找遍历过长的已删除序列 需要周期性重建(Rehash):当墓碑比例超过阈值(如 30%),需要重新插入所有存活元素 // 墓碑导致的查找效率下降示意 [ A ] [ 墓碑 ] [ 墓碑 ] [ 墓碑 ] [ B ] [ 空 ] // 查找 B:需要跳过 3 个墓碑,即使它们是空的,线性探测依然要检查 1.4 线性探测的"真香"场景 尽管有上述缺陷,线性探测在工业界依然被广泛使用,原因在于: ...

2026-07-11 05:00:18 PM · 2 分钟

Docker Healthcheck 万金油

模板一:网络服务万金油(只要有网络端口,通杀) 如果容器是 Web 服务(如 Nginx、Tomcat、Node.js)、数据库(如 Redis、MySQL)或者各种中间件,只要它暴露了 TCP 端口,且容器内带有最基础的 sh,这就是最无敌的万金油配置。 它利用了 Linux 内核原生 </dev/tcp 漏洞,完全不依赖 curl 或 wget 。 healthcheck: # 语法解释:尝试与容器本地的 8080 端口建立 TCP 连接,失败则退出码为 1 test: ["CMD-SHELL", "sh -c '</dev/tcp/127.0.0.1/8080' || exit 1"] interval: 10s # 10秒探一次,既保证敏锐度,又不会给系统带来TCP连接压力 timeout: 3s # 握手超过3秒没反应,说明网络栈或主线程已经卡死 retries: 3 # 连续失败3次(大约30秒内)正式宣判死刑 start_period: 30s # 30秒新手保护期,给服务腾出启动和绑定端口的时间 注:使用时只需要把 8080 改成你容器内部的实际端口(如 Redis 改成 6379,Nacos 改成 8848)即可。 模板二:Java/Spring Boot 专属万金油(解决高 CPU 与 Full GC 假死) 对于 Java 应用,有时候端口虽然勉强能连上,但实际上 JVM 内部因为内存溢出(OOM)或者恐怖的 CPU 占用,已经完全无法处理业务了。 这时候用 Java 自带的诊断工具 jcmd 去拍 JVM 的脑袋,是最精准的万金油手段(前提是使用 JDK 镜像,非精简的 JRE)。 ...

2026-07-11 04:30:54 PM · 1 分钟

过家家项目:我是如何设计亲属称谓计算引擎的? 更新中 

正在更新中

2026-07-11 11:30:58 AM · 1 分钟

过家家项目:一款专注于家庭的应用

开发者警告:这是一个 Alpha 版本 Github 网址: 部分功能仍在测试阶段,稳定性有待验证。请勿擅自用于任何商业用途,仅供学习参考 🏡 SweetHome — 过家家 项目官网:https://www.sweethome.asia 面向家庭的社交与智能生活平台后端 从家庭关系图谱出发,重新定义家人之间的连接方式 功能特性 · 系统架构 · 技术栈 · 模块说明 · 快速开始 · API 概览 · 设计亮点 APP页面展示 ✨ 功能特性 👨‍👩‍👧‍👦 家庭关系管理 家庭创建与加入 — 注册即创建家庭,或通过邀请码/管理员审批加入 亲属关系引擎 — 基于图的 BFS 最短路径算法,自动计算成员间的称谓(爷爷、舅舅、堂姐…),服务端只产出语言无关的 relationCode,本地化由客户端完成 多家庭切换 — 用户同一时刻只属于一个家庭,切换时自动级联退出旧家庭 💬 即时通讯 WebSocket 实时聊天 — 原生 WebSocket(非 STOMP),支持文本/图片/语音/视频/红包消息 Redis Pub/Sub 广播 — 支持多实例水平扩展,消息通过 Redis 频道在各实例间扇出 HTTP 兜底 — WebSocket 断线时降级到 REST 接口发送 未读计数 — 基于游标的消息状态跟踪 💰 电子红包 Lua 脚本保证原子性 — 抢红包操作在 Redis 中原子执行,支持高并发 Redis Stream 持久化 — 红包领取记录先进入 Stream,由后台消费者异步落库 自动过期 — 定时任务将过期红包退款 📍 位置服务 实时位置上报 — 家庭成员位置追踪 电子围栏 — 自定义地理围栏,越界告警(通过极光推送通知) 📸 家庭动态(Moments) 图文/视频动态 — 类似朋友圈的家庭动态 点赞与评论 — 互动功能 公共动态广场 — 跨家庭动态聚合 ❤️ 健康管理 健康指标记录 — 身高、体重、血压,按日追踪 可见性控制 — 每项指标可独立设置对家人公开/私密 每日提醒 — 定时推送提醒记录健康数据 🔐 安全认证 JWT 双 Token — accessToken(15 分钟)+ refreshToken(30 天) 网关统一认证 — 所有请求统一在 Gateway 层鉴权,下游服务信任 X-User-Id 头 RSA 非对称签名 — 仅 auth-service 持有私钥签发,其他服务只持公钥验证 ☁️ 云原生基础设施 Nacos — 服务注册发现 + 配置中心(共享配置) Dubbo — 服务间 RPC 调用(最长 3 跳链路:auth → user → family → chat) Kafka — 事件驱动(缓存失效广播、围栏告警、离线通知、健康提醒) JPush — 极光推送,App 后台时接收告警通知 Caffeine + Redis — 两级缓存,热点数据就近加速 Cloudflare R2 — 对象存储(头像、聊天图片、视频、语音) 🌐多语言支持 ✅ 中文简体 ✅ 中文繁体 ✅ 英语 ✅ 缅甸语(AI翻译,未进行人工测试) ✅ 韩语(AI翻译,未进行人工测试) ✅ 日语(AI翻译,未进行人工测试) ...

2026-07-11 11:29:18 AM · 7 分钟

JAVA程序员防翻车指南

一、基础类型与字面量(1-10) int 最大值 2,147,483,647(2³¹-1),最小值 -2,147,483,648(-2³¹) long 最大值 9,223,372,036,854,775,807(2⁶³-1),字面量加 L float 字面量必须加 f,否则默认 double short 范围 -32,768 ~ 32,767,byte 范围 -128 ~ 127 字面量下划线:1_000_000 等于 1000000,仅 Java 7+ 0x 开头是十六进制,0b 开头是二进制,0 开头是八进制(容易误判) char 占 2 字节,Character.SIZE = 16,但 Unicode 扩展字符需 2 个 char(surrogate pair) boolean 只有 true/false,不能和 0/1 互转(和 C 不同) Integer.valueOf(127) == Integer.valueOf(127) 为 true,128 为 false(缓存池 -128~127) Integer.parseInt("") 抛 NumberFormatException,Integer.parseInt(null) 也抛 二、运算符与表达式(11-18) & 和 && 区别:& 两边都执行(位运算或逻辑与),&& 短路 | 和 || 同理,|| 短路 ^ 按位异或,~ 按位取反(包含符号位) >> 算术右移(补符号位),>>> 无符号右移(补 0) i++ 和 ++i 的字节码区别:前者先加载后自增,后者先自增后加载 += 隐式类型转换:short s = 1; s += 1; 合法,s = s + 1; 编译错误 三元运算符 ? : 必须返回相同类型,否则自动类型提升 字符串拼接用 + 在循环内会生成大量 StringBuilder,循环外编译器自动优化 三、String 相关(19-28) String 不可变,底层 char[] 被 final 修饰且不暴露修改方法 字符串常量池在堆中(Java 8+),intern() 手动入池 new String("abc") 创建 2 个对象(常量池 + 堆),"abc" 只创建 1 个(若池中没有) String.equals() 比较内容,== 比较引用地址 String.compareTo() 按字典序比较,返回差值 String.format() 使用 %s %d %f 占位符 substring() 在 Java 7 前共享 char[],Java 7+ 创建新数组(解决内存泄漏) split() 参数是正则,. 需转义为 \\. replace() 替换所有字符,replaceAll() 支持正则 StringBuilder 线程不安全,StringBuffer 线程安全(方法加 synchronized),但慢 四、equals 与 hashCode(29-34) 重写 equals 必须重写 hashCode,否则 HashMap/HashSet 失效 equals 必须满足:自反、对称、传递、一致、非空(x.equals(null) 返回 false) hashCode 相等的两个对象 equals 不一定相等(哈希冲突) Objects.equals(a, b) 自动判空,避免 null.equals() Arrays.deepEquals() 比较多维数组,Arrays.equals() 只比较一维 List.equals() 要求顺序相同,Set.equals() 仅要求元素相同(顺序无关) 五、异常处理(35-44) try-catch-finally 中 finally 在 return 之前执行,但返回值已在 finally 前计算好 finally 中有 return 会覆盖 try/catch 的返回值 finally 中修改返回的引用对象内容会生效(如 List.add()) 不要在 finally 中写 return,也不要在其中抛出异常(会掩盖原始异常) try-with-resources 要求资源实现 AutoCloseable,关闭顺序:先声明的后关闭 受检异常(Exception 子类)必须 try-catch 或 throws,RuntimeException 非受检 异常链:catch (SQLException e) { throw new RuntimeException(e); } 保留堆栈 printStackTrace() 不应用在生产日志中,用 log.error("msg", e) Throwable 包括 Error 和 Exception,Error 不应该捕获(如 OutOfMemoryError) finally 中关闭资源时可能抛异常,要用 try-catch 包裹或使用 try-with-resources 六、集合框架(45-62) ArrayList 初始容量 10,扩容 1.5 倍(oldCapacity + (oldCapacity >> 1)) ArrayList 随机访问 O(1),中间插入删除 O(n),LinkedList 相反 LinkedList 实现了 Deque,可作为队列/栈使用 HashMap 容量为 2 的幂,默认 16,负载因子 0.75,扩容 2 倍 HashMap 索引计算:(n - 1) & hash,hash = key.hashCode() ^ (h >>> 16) Java 8+ HashMap 链表长度 > 8 且容量 >= 64 时转红黑树,< 6 时退化为链表 HashMap 的 key 为 null 时,hash 值为 0,存在 table[0] ConcurrentHashMap 分段锁(Java 7)→ synchronized + CAS(Java 8+) Hashtable 线程安全但全表锁,已淘汰 TreeMap 基于红黑树,有序(按 key 自然序或 Comparator) LinkedHashMap 按插入顺序或访问顺序(accessOrder=true 可实现 LRU) HashSet 底层是 HashMap,TreeSet 底层是 TreeMap PriorityQueue 小顶堆,Comparator.reverseOrder() 可转大顶堆 ArrayDeque 优于 Stack(Stack 已废弃,ArrayDeque 线程不安全但更快) Collections.synchronizedList() 包装为线程安全,但迭代时仍需手动同步 CopyOnWriteArrayList 读多写少场景,写时复制整个数组 List.of() / Set.of()(Java 9+)返回不可变集合,不能增删改 ArrayList.subList() 返回视图,对子列表操作会影响原列表,反之亦然 七、并发与线程(63-80) 创建线程的三种方式:Thread、Runnable、Callable(有返回值) start() 启动线程,run() 只是普通方法调用 synchronized 可锁实例方法、静态方法(锁 Class)、代码块 wait() 释放锁,sleep() 不释放锁,yield() 让出 CPU 但不释放锁 wait()/notify() 必须在 synchronized 块中调用,否则抛 IllegalMonitorStateException notify() 随机唤醒一个,notifyAll() 唤醒全部 死锁四条件:互斥、请求与保持、不可抢占、循环等待 破坏死锁:按固定顺序加锁、tryLock() 超时、使用 ReentrantLock volatile 保证可见性和有序性(禁止指令重排),不保证原子性 AtomicInteger 用 CAS 实现原子操作,incrementAndGet() 底层是 Unsafe.compareAndSwapInt ThreadLocal 用完后必须 remove(),否则线程池复用导致内存泄漏 ThreadLocal 底层是 ThreadLocalMap,key 是弱引用,value 是强引用 ExecutorService 用 shutdown() 优雅关闭,shutdownNow() 立即关闭 线程池核心参数:核心线程数、最大线程数、存活时间、阻塞队列、拒绝策略 四种拒绝策略:AbortPolicy(抛异常)、CallerRunsPolicy(调用者执行)、DiscardPolicy(丢弃)、DiscardOldestPolicy(丢弃最旧) CachedThreadPool 最大线程数 Integer.MAX_VALUE,容易 OOM,慎用 FixedThreadPool 使用无界队列,任务积压可能导致 OOM Future.get() 阻塞,CompletableFuture 异步回调更灵活 八、I/O 与 NIO(81-88) File 只是路径抽象,不表示真实文件,exists() 判断是否存在 FileInputStream 读取字节,FileReader 读取字符(默认编码可能乱码) BufferedReader 用 readLine() 按行读取,Files.readAllLines() 更简洁 InputStreamReader 可指定字符集:new InputStreamReader(new FileInputStream("a.txt"), StandardCharsets.UTF_8) try-with-resources 自动关闭多个资源,用分号分隔 Path/Paths/Files(Java 7+)替代 File,Files.walk() 遍历目录树 NIO 核心:Channel + Buffer + Selector(多路复用) ByteBuffer 读写切换需调用 flip(),clear() 清空,compact() 压缩 九、JVM 与内存(89-95) JVM 内存区域:堆、栈、方法区(元空间)、程序计数器、本地方法栈 堆分代:年轻代(Eden + S0 + S1)→ 老年代,默认比例 8:1:1 OutOfMemoryError 常见原因:堆 OOM、元空间 OOM、直接内存 OOM、栈溢出 栈溢出 StackOverflowError,递归过深或无终止条件 System.gc() 仅建议 GC,不保证执行 finalize() 已废弃(Java 9+),对象自救不靠谱 类加载器:Bootstrap(rt.jar)→ Extension → Application,双亲委派模型 十、日期与时间(96-100) java.util.Date 可变、线程不安全,已废弃,用 java.time.*(Java 8+) LocalDate / LocalTime / LocalDateTime 不含时区,ZonedDateTime 含时区 Instant 时间戳(秒/纳秒),Duration 计算时间差,Period 计算日期差 格式化用 DateTimeFormatter 线程安全,替代 SimpleDateFormat(线程不安全) LocalDateTime.now() 获取当前时间,parse("2026-07-09") 按 ISO 标准解析 十一、语法糖与常见坑(101-110) 泛型编译期擦除,运行时无泛型信息(List<String> 和 List<Integer> 在运行时相同) 可变参数本质是数组,public void method(String... args) 可传数组或逗号分隔 枚举 enum 默认继承 Enum,不能被继承,构造器私有 匿名内部类持有外部类引用(this$0),可能导致内存泄漏 接口默认方法 default,静态方法 static,接口中变量默认 public static final 抽象类可有构造器,接口无构造器 switch 支持 byte/short/char/int/String/enum,不支持 long/float/double break 跳出循环,continue 跳过本次,return 结束方法 标签 label: 可跳出外层循环,但不推荐使用 数组协变:String[] 是 Object[] 的子类,但集合泛型不变 十二、网络与反射(111-118) URL 和 URI 区别:URI 是标识符,URL 是定位符(包含协议) HttpURLConnection 原生 HTTP 客户端,但 Apache HttpClient / OkHttp 更常用 Socket 阻塞 I/O,ServerSocket 监听端口,accept() 阻塞等待连接 反射 Class.forName() 初始化类,ClassLoader.loadClass() 不初始化 Method.invoke() 性能差,但反射能绕过私有访问(setAccessible(true)) Proxy.newProxyInstance() 动态代理只能代理接口,CGLIB 可代理类 注解保留策略:SOURCE(源码)、CLASS(字节码)、RUNTIME(运行时) 序列化实现 Serializable 接口,serialVersionUID 用于版本兼容,不声明则自动生成 十三、设计原则与模式(119-123) 单例双重检查需 volatile,防止指令重排导致半初始化对象被读取 工厂模式解耦,策略模式消除 if-else,观察者模式事件驱动 依赖倒置:依赖抽象而非具体实现 开闭原则:对扩展开放,对修改封闭 里氏替换:子类可以替换父类出现的地方 十四、Linux 与常用命令(124-128) nohup java -jar app.jar & 后台运行,输出到 nohup.out jps 查看 Java 进程,jstack 打印线程堆栈,jmap 查看堆内存,jstat 监控 GC kill -15 优雅关闭(SIGTERM),kill -9 强制杀死(SIGKILL) tail -f app.log 实时查看日志,grep -C 10 "error" app.log 显示上下文 netstat -tlnp 查看端口占用,lsof -i:8080 查看指定端口 十五、数据库与 JDBC(129-133) PreparedStatement 防 SQL 注入,占位符 ?,编译一次执行多次 Statement 拼接字符串有注入风险,不用 ResultSet 游标从 1 开始,next() 移动指针,getString(1) 按索引取 事务隔离级别:读未提交、读已提交、可重复读、串行化 连接池用 HikariCP(默认)、Druid,不要手动创建连接 十六、Maven / Gradle(134-137) Maven 生命周期:clean → compile → test → package → install → deploy provided 作用域表示运行时由容器提供(如 servlet-api) 依赖传递:compile 传递,test 不传递,provided 不传递 版本冲突用 dependencyManagement 锁定版本,或用 exclude 排除 十七、工具与调试(138-142) System.out.println() 性能差,生产用日志框架(SLF4J + Logback) 日志级别:ERROR > WARN > INFO > DEBUG > TRACE assert 默认禁用,需 -ea 开启,生产慎用 Objects.requireNonNull() 判空抛 NullPointerException,比手动 if 简洁 Optional 用来表示可能为 null 的返回值,不要用作字段或参数 十八、编码规范与常识(143-150) 包名全小写,类名大驼峰,方法/变量小驼峰,常量全大写 + 下划线 方法名用动词(getUser),变量名用名词(userName) 布尔变量用 is / has / can 开头(isDeleted) 一个 .java 文件只能有一个 public 类,文件名必须和 public 类名一致 构造器不能 static,不能被 final 修饰 static 块在类加载时执行一次,{} 实例块在构造器前执行 匿名对象(new User())用完即抛,适合单次使用 永远不要在线上环境用 System.out 打印大对象,更不要用 e.printStackTrace()

2026-07-09 10:15:46 PM · 4 分钟

漫谈AI上下文长度

flowchart TD A[2018–2021512–2K Token金鱼记忆时代] -->|只能处理短文、短句、单轮问答| B[2022–20234K–128K Token中上下文普及时代] B -->|可处理论文、合同、小说、中型代码库RAG 成为企业标准方案| C[2024–2025200K–1M Token百万上下文实验期] C -->|纸面支持 1M,但遗忘、成本、速度问题明显仅限量 Beta| D[2026–20271M–2M Token1M 量产普惠时代] D -->|1M 成为旗舰标配可处理整卷宗、整代码库、全年业务日志| E[2028–20292M–10M Token超百万窗口分化时代] E -->|2M 以上面向行业定制长视频、大型代码库、多年日志联合分析| F[2030+10M+ 弹性记忆原生长记忆智能体时代] 一、大模型上下文完整进化时间线(2018–2026,分4个时代) 1. 初代Transformer时代:512–2K(2018–2021,金鱼记忆) 2018 GPT-1 / BERT:512 token,仅短文、短句分类,多轮对话必丢前文 2019 GPT-2:1024 token,能写短篇故事,连续对话3–5轮就遗忘历史 2020 GPT-3:2048 token(2K),行业通用标准,仅支持短提示词、少量示例,长文档必须分段/摘要处理 2021 早期国产(文心一言初代、GLM-1):统一2K上限,无长文本能力 时代特征:没有原生长文本能力,所有长内容必须靠人工拆分、外部摘要,RAG雏形出现。 2. 中上下文普及时代:4K–128K(2022–2023,工业化可用) 2022 ChatGPT(GPT-3.5):4K;年末升级16K,日常聊天够用,长文档仍吃力 2023.3 GPT-4 首发:8K,专业文档、代码单文件处理门槛打开 2023.7 Claude 2:100K,首个量产十万级窗口,法律、长篇论文场景爆发 2023.11 GPT-4 Turbo:128K,全球主流商用标配门槛,单本小说完整载入 2023年底 国产跟进:通义、GLM、混元开放32K/64K;开源Llama 2、Qwen 7B固定4K–32K 2023.12 Gemini 1.0 Ultra 纸面宣称1M,但仅实验室封闭测试,无法商用落地 时代里程碑:128K成为专业AI标配;RAG成为行业标准方案,弥补窗口不足。 3. 百万上下文实验期:200K–2M纸面(2024–2025,纸面强、实际弱) 2024.2 Gemini 1.5 Pro:原生2M token,全球首个公开百万级模型,但存在严重「中间遗忘Lost in the Middle」,后半段文档召回暴跌,仅适合摘要,不适合精细推理,仅限开发者限量Beta 2024 Claude 3 Opus:200K,稳定可靠,法律行业主力,无严重遗忘问题 2025 上半年:各大厂商放出1M Beta(Claude Sonnet 4、Gemini 2.0),长上下文计费溢价极高、响应慢、显存开销巨大,企业少量试用,普通用户无法接触 2025 国产开源:Qwen、DeepSeek推出64K–128K底座,少量实验版支持256K 时代特征:1M只是技术噱头,标称≠有效;硬件成本、遗忘问题、价格三重门槛,无法大规模落地。 ...

2026-07-09 08:58:34 PM · 2 分钟

一个程序员应该知道的各种锁

1. 悲观锁 vs 乐观锁(心态问题) 悲观锁:觉得肯定有人抢厕所,进去就反锁门(加锁),用完再开。 → Java里的 synchronized 和 ReentrantLock 都是这种。安全,但慢。 乐观锁:觉得没人抢,不锁门,但上厕所时盯着门把手(版本号/时间戳),如果发现被人动过(冲突),就重试。 → Java里的 CAS(比较并交换) 就是这种,比如 AtomicInteger。快,但冲突多时会反复重试。 2. 公平锁 vs 非公平锁(排队问题) 公平锁:先来后到,乖乖排队。 → new ReentrantLock(true)。公平,但效率低(大家都得排队)。 非公平锁:新来的可以插队,如果锁刚好释放,它就直接抢。 → synchronized 和默认的 ReentrantLock 都是非公平。效率高,但可能导致某些线程饿死(一直抢不到)。 3. 可重入锁(同一个人的多次进入) 你进了厕所A,发现里面还有个小隔间B,你能直接进B,不用再掏钥匙。 → synchronized 和 ReentrantLock 都支持。同一个线程可以多次获取同一把锁,防止自己把自己卡死。 4. 读写锁(分情况管理) 厕所分蹲位(写锁)和洗手池(读锁)。 多人同时洗手(读)没问题。 但有人蹲坑(写)时,别人既不能蹲也不能洗手(全阻塞)。 → ReentrantReadWriteLock。适合读多写少的场景。 5. 共享锁 vs 排他锁(权限级别) 排他锁(写锁):厕所门一锁,谁也别进。 共享锁(读锁):可以多人同时看同一份文件(但不能改)。 → 读写锁就是共享/排他的典型实现。 6. 偏向锁 → 轻量级锁 → 重量级锁(锁升级,JVM自动优化) 这是 synchronized 的底层升级过程(为了性能): 偏向锁:厕所只认你一个人,你每次来都不用掏钥匙(无竞争)。 轻量级锁:偶尔有别人来,你们用“自旋”方式(原地转圈等)抢,不挂起线程(省资源)。 重量级锁:竞争激烈,排队挂起(操作系统介入,慢)。 → 这是JVM自动做的,你不用管,但知道它存在即可。 7. 自旋锁(不睡觉,死等) 厕所被占,你不去排队睡觉,而是在门口原地转圈(循环检查),等它释放。 → 适合持有锁时间很短的情况,避免线程挂起/唤醒的开销。Java里的 CAS 就是自旋思想。 8. 分段锁(分块管理) 一个大厕所分成多个小隔间,锁只锁其中一间,不影响其他间。 → ConcurrentHashMap 早期就是用分段锁,提升并发度(现在改用CAS+细粒度锁了)。 一张图总结(按使用场景选): 场景 推荐锁 简单同步,代码少 synchronized 需要可中断、超时、公平等灵活功能 ReentrantLock 读多写少(如缓存) ReentrantReadWriteLock 计数器、自增等简单操作 AtomicXXX(乐观锁) 追求极致性能,竞争不激烈 偏向锁/轻量级锁(JVM自动)

2026-07-09 11:15:34 AM · 1 分钟