我要开一个超市,超市里面卖的是“数据库和中间件(4)”
第六章:超市精细化运营——补齐剩余核心知识点
6.1 收银台排队:Redis List模拟队列
超市收银台排队,可以用Redis的List结构模拟一个先进先出的队列。顾客结账时,LPUSH订单号到队列,收银员处理完后RPOP。
List底层:当元素少时用ziplist,多时用linkedlist(quicklist)。quicklist是ziplist和linkedlist的结合,每个节点是一个ziplist,节省内存且支持两端操作。
应用场景:除了收银队列,还可以用于异步任务(如发短信),但生产环境更推荐消息队列(因为Redis List不支持消息确认、重试)。不过,对于简单的、允许丢失的场景,List足够轻量。
6.2 会员标签:Redis Set实现精准营销
超市想给会员打标签(如“高消费”、“生鲜爱好者”),用于定向推送。用Redis Set存储每个标签下的用户ID集合。
Set底层:元素全为整数且数量少时用intset(有序数组),否则用hashtable。
集合运算:计算“高消费且生鲜爱好者”的交集,用sinterstore,结果存入新key,后续推送用。
Bitmaps替代:如果标签数量固定且用户量大,可以用Bitmaps(如第1位表示高消费,第2位表示生鲜),占用内存极小。
6.3 店铺附近的人:Redis Geo实现LBS
超市要推“附近门店”功能,根据用户坐标查找最近的门店。
Geo底层:基于Sorted Set实现,将经纬度编码为52位整数(Geohash),作为score存入。
操作:geoadd添加门店位置,georadius根据用户坐标查询附近门店(支持距离、排序)。
原理:Geohash将二维坐标降为一维字符串,相同前缀表示邻近区域,通过score范围快速定位。
6.4 超市日活统计:HyperLogLog
运营需要统计每天到店用户数(UV),精确计数可以用Set,但用户量巨大时内存吃不消。
HyperLogLog:用概率算法,占用12KB内存,标准误差0.81%,能统计2^64个元素。
用法:PFADD添加用户ID,PFCOUNT统计。多个店铺的日活可以PFMERGE合并。
6.5 库存预警:Redis发布订阅
当某商品库存低于阈值时,通过Redis的发布订阅实时通知店员补货。
发布订阅:PUBLISH到频道,所有订阅该频道的客户端接收消息。但消息不会持久化,如果客户端不在线就丢失,适合实时性高但可容忍丢失的场景。
6.6 缓存淘汰策略:当Redis内存满了
超市客流太大,Redis内存告急,需要配置淘汰策略。
maxmemory-policy:
- volatile-lru:从已设置过期时间的key中淘汰最近最少使用的。
- allkeys-lru:从所有key中淘汰最近最少使用的(常用)。
- volatile-lfu:从已设置过期时间中淘汰最不经常使用的。
- allkeys-lfu:淘汰最不经常使用的。
- volatile-ttl:淘汰即将过期的。
- noeviction:返回错误(默认)。
LRU vs LFU:LRU只考虑最近访问时间,LFU考虑访问频率,适合某些热点偶尔访问的场景。
近似LRU:Redis的LRU是近似实现,随机采样N个key淘汰最旧的,可通过maxmemory-samples调整精度。
6.7 MySQL binlog深入:三种格式
Canal同步数据到ES时,需要理解binlog格式。
- STATEMENT:记录SQL语句,体积小,但某些语句(如UUID())可能不一致。
- ROW:记录每行变更,准确但体积大,Canal必须用ROW格式。
- MIXED:混合模式,默认用STATEMENT,不确定时用ROW。
ROW格式下的镜像:binlog包含变更前后的完整行数据,可用于数据恢复和异构同步。
6.8 MySQL高可用:MGR(组复制)
超市系统需要更高的可用性,引入MySQL Group Replication。
MGR原理:基于Paxos协议的组通信,多个节点组成复制组,支持多主或单主模式。
- 多主模式:任何节点可写,需处理冲突检测。
- 单主模式:只有一个主节点,其他自动选主。
对比传统主从:MGR自动故障转移,数据强一致,但性能稍差,网络要求高。
6.9 微服务安全:OAuth2 + JWT
超市会员系统需统一认证,用OAuth2颁发token。
JWT结构:header.payload.signature,自包含用户信息,无状态。
认证流程:客户端登录,认证服务验证后返回JWT,后续请求携带JWT,网关解析并转发用户信息。
JWT vs Session:JWT避免Session共享,但无法主动失效(除非用黑名单)。
Spring Security集成:通过OAuth2资源服务器配置,解析JWT。
6.10 全链路压测:模拟双十一
双十一前,对超市系统进行全链路压测,找出瓶颈。
压测工具:JMeter、Locust、阿里PTS。
压测策略:
- 逐步增加并发,观察QPS、RT、CPU、内存、GC。
- 发现瓶颈后优化(加索引、扩容、调参)。
- 全链路压测需考虑数据隔离(测试数据不影响线上)。
影子表:在MySQL中创建同名影子表,压测流量路由到影子表,避免污染真实数据。
6.11 混沌工程:故意搞破坏
为验证系统韧性,引入混沌工程。
工具:ChaosBlade、Litmus。
实验:随机杀死Pod、延迟网络、CPU满载,观察系统是否降级、熔断、恢复。
超市例子:模拟一个订单服务实例宕机,看网关是否自动重试到其他实例,Sentinel是否触发熔断。
6.12 任务调度进阶:DAG工作流
XXL-JOB支持任务依赖(DAG),用于复杂的报表生成流程。
示例:日报生成任务 -> 周报聚合任务 -> 邮件发送任务,依次依赖。
实现:通过任务分片和回调,或使用Apache Airflow这类专业工作流引擎。
6.13 消息队列选型:为什么选RocketMQ
假设超市未来要对接Kafka,需要知道选型依据。
- RocketMQ:适合电商交易,支持事务消息、延迟消息、死信队列,社区在阿里,Java系友好。
- Kafka:适合日志、大数据吞吐,分区多副本,但事务支持较弱。
- RabbitMQ:轻量,支持多种协议,但吞吐量不如前两者。
选型时考虑:是否需事务、延迟消息、吞吐量、开发语言生态。
6.14 服务网格进阶:Istio流量管理
引入Istio实现更精细的流量控制。
VirtualService:定义路由规则,如10%流量到新版本(金丝雀发布)。
DestinationRule:定义负载均衡、连接池。
故障注入:模拟延迟或异常,测试服务容错。
超市例子:新会员服务上线,只让内部员工账号流量切过去,验证无误后全量。
6.15 Helm:K8s包管理
超市服务越来越多,用Helm统一打包部署。
Chart:包含模板和values.yaml,可参数化配置。
Release:部署到K8s的一个实例。
钩子:在安装、升级时执行特定任务(如数据库初始化)。
6.16 Operator:自动化运维
用Operator管理有状态应用,如Redis Operator、MySQL Operator。
原理:自定义控制器监听CRD(自定义资源),根据期望状态自动调整集群(如故障转移、扩缩容)。
6.17 业务监控:自定义指标
除了基础设施监控,还需监控业务指标(如订单量、销售额)。
实现:用Micrometer埋点,暴露给Prometheus,Grafana展示。
告警:订单量暴跌可能意味着系统故障,触发告警。
6.18 全链路压测数据隔离
压测流量如何识别?
请求头标记:压测工具添加x-request-source: stress,网关识别后将请求路由到影子库。
影子库:在MySQL、Redis中准备影子库/表,所有写操作落到影子区,不影响线上数据。
6.19 设计模式补遗
- 工厂方法:在Spring中创建Bean。
- 抽象工厂:用于不同中间件客户端创建(如JedisConnectionFactory)。
- 建造者模式:RedisTemplate的配置。
- 原型模式:Bean的作用域prototype。
- 适配器模式:Spring MVC的HandlerAdapter。
- 装饰器模式:BufferedInputStream包装。
- 代理模式:AOP。
- 外观模式:门面服务封装复杂调用。
- 策略模式:负载均衡算法。
- 模板方法:JdbcTemplate、RedisTemplate。
- 观察者模式:Spring事件监听。
- 责任链模式:Sentinel的ProcessorSlotChain。
- 命令模式:Runnable。
- 状态模式:工作流状态机。
- 访问者模式:ASM字节码操作。
- 中介者模式:消息队列解耦。
6.20 JVM细节补充
- 直接内存:Netty使用DirectByteBuffer,需监控
-XX:MaxDirectMemorySize。 - 类加载机制:双亲委派模型,Tomcat打破双亲委派隔离应用。
- 逃逸分析:栈上分配、同步消除。
- TLAB:线程本地分配缓冲区,减少锁竞争。
- GC日志分析工具:GCeasy、GCEasy。
6.21 并发编程补充
- Fork/Join框架:用于并行计算,如统计所有门店销售数据。
- CompletableFuture:实现异步编排,如同时调用商品、库存、营销服务。
- ThreadLocal:存储用户上下文,但需注意内存泄漏(remove)。
- AQS:AbstractQueuedSynchronizer,ReentrantLock、CountDownLatch等的基础,实现同步状态管理。
6.22 网络协议细节
- HTTP/2:多路复用、头部压缩,Gateway可开启。
- gRPC:基于HTTP/2,使用Protobuf,适合内部高性能RPC。
- WebSocket:用于实时推送(如库存预警)。


