一、微服务与 SpringCloud

1. 架构演进

  • 单体架构:所有功能打成一个包部署。优点:简单、部署成本低;缺点:耦合度高、维护/升级困难。适合小项目。
  • 分布式架构:按业务功能拆成独立项目(服务)。优点:降低耦合、易扩展;缺点:调用关系复杂。
  • 微服务:一种"良好设计的分布式架构"。四大特征:单一职责(粒度更小)、自治(团队/技术/数据/部署独立)、面向服务(标准接口、跨语言)、隔离性强(隔离+容错+降级)。做到高内聚、低耦合。

微服务不是具体技术,而是一种架构标准;SpringCloud 是它的一站式落地方案。

2. SpringCloud 是什么

  • 国内最主流的微服务框架,官网 https://spring.io/projects/spring-cloud。
  • 集成了各种微服务功能组件,并基于 SpringBoot 自动装配,开箱即用。
  • 常见组件:注册中心、配置中心、远程调用、负载均衡、网关、熔断限流等。
  • 版本关系:SpringCloud 依赖 SpringBoot。

二、服务拆分与远程调用

1. 拆分原则

  • 不同微服务不要重复开发相同业务。
  • 微服务数据独立,不要访问其它微服务的数据库。
  • 微服务把自己的业务暴露为接口,供其它服务调用。

2. 远程调用(RestTemplate 原始方式)

// 1. 在启动类注册 RestTemplate
@Bean
public RestTemplate restTemplate(){ return new RestTemplate(); }

// 2. 注入并调用
String url = "http://localhost:8081/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);
  • 服务提供者:被其它微服务调用的服务(提供接口)。
  • 服务消费者:调用其它微服务的服务。
  • 角色是相对的:A 调 B、B 调 C,则 B 既是消费者也是提供者。

3. 痛点

硬编码 IP+端口、无法负载均衡、无服务健康感知 → 引入注册中心。


三、注册中心:Eureka 与 Nacos

1. 为什么需要注册中心

  • 服务有多个实例时,消费者如何知道实例地址?如何选一个?如何感知宕机?
  • 注册中心解决:服务注册、服务发现(拉取)、心跳续约、剔除故障实例。

2. Eureka 结构

  • eureka-server:独立微服务,保存"服务名 → 实例地址列表"映射。
  • eureka-client:每个微服务引入,既注册又发现。
  • 流程:实例启动注册 → 消费者按服务名拉列表 → Ribbon 负载均衡选一个 → 实例每 30s 发心跳,超时不跳则剔除。

关键配置:

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
spring:
  application:
    name: userservice

3. Nacos(阿里,国内主流)

  • 功能比 Eureka 丰富,既是注册中心也是配置中心。
  • 引入依赖(注意注释掉 eureka 依赖):
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

spring:
  cloud:
    nacos:
      server-addr: localhost:8848

4. Nacos 核心概念

  • 分级存储模型:服务 → 集群(如 HZ 杭州、SH 上海)→ 实例。同集群优先访问,跨机房才访问其它集群。
  • 权重配置:控制台改实例权重,权重越大访问越多;权重=0 永不被访问。用于让性能好机器多扛量。
  • 环境隔离 namespace:不同 namespace 的服务互相不可见(默认 public)。可通过命名空间 ID 隔离 dev/test/prod。

5. Nacos vs Eureka

对比NacosEureka
服务注册/拉取都支持都支持
健康检查临时实例心跳;非临时实例主动检测仅心跳
实例剔除临时实例不正常才剔除;非临时不剔除不正常即剔除
列表更新支持变更推送,更及时定时拉取
一致性默认 AP,含非临时实例时 CPAP

临时实例:ephemeral: false 设为非临时(永久)实例。


四、负载均衡 Ribbon

  • SpringCloud 底层用 Ribbon 实现负载均衡。给 RestTemplate 加 @LoadBalanced 即可用服务名代替 IP。
  • 原理:LoadBalancerInterceptor 拦截请求 → 从 Eureka 按服务名取实例列表 → IRule 选一个 → 替换 URL 发起真实请求。
  • 内置策略:RoundRobinRule(轮询,默认)、RandomRule、WeightedResponseTimeRule、RetryRule 等。一般用默认即可。
  • 饥饿加载(避免首次慢):
ribbon:
  eager-load:
    enabled: true
    clients: userservice

五、配置管理:Nacos Config

1. 统一配置管理

  • 实例多了逐个改配置易错 → Nacos 集中管理,且支持热更新。
  • 核心配置、需要热更新的配置才放 Nacos;基本不变的留本地。
  • 读取顺序:先读 bootstrap.yaml(在 application.yml 之前),得知 Nacos 地址,再拉取配置合并。
# bootstrap.yaml
spring:
  application:
    name: userservice
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml

文件 ID 规则:${spring.application.name}-${profiles.active}.${file-extension} → 例 userservice-dev.yaml。

2. 配置热更新(两种方式)

  • 方式一:在 @Value 所在类加 @RefreshScope。
  • 方式二(推荐):用 @ConfigurationProperties(prefix="pattern") 代替 @Value,自动刷新。

3. 配置共享

  • userservice.yaml(无环境)可被多环境共享;userservice-dev.yaml 仅 dev。
  • 优先级(高→低):Nacos 当前环境配置 > Nacos 共享配置 > 本地 application.yml > bootstrap。
  • 生产务必部署 Nacos 集群(非单机)。

六、声明式 HTTP 调用:Feign

RestTemplate 代码可读性差、URL 难维护 → 用 Feign(声明式 http 客户端)。

1. 基本使用

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

@EnableFeignClients        // 启动类开启
@FeignClient("userservice") // 声明客户端
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
// 调用:userClient.findById(userId) 即可,无需手写 RestTemplate

2. 自定义配置

类型作用
Logger.Level日志级别 NONE/BASIC/HEADERS/FULL
Decoder/Encoder响应解析/请求编码
Retryer失败重试

配置(针对某服务或全局 default):

feign:
  client:
    config:
      userservice:
        loggerLevel: FULL

3. 性能优化(★重点)

  • Feign 底层默认用 URLConnection(无连接池)。改用 HttpClient/OKHttp 连接池:
<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-httpclient</artifactId>
</dependency>

feign:
  httpclient:
    enabled: true
    max-connections: 200
    max-connections-per-route: 50
  client:
    config:
      default:
        loggerLevel: BASIC

4. 最佳实践(抽取)

  • 把 FeignClient、相关 POJO、默认配置抽到独立模块 feign-api,各消费者引入依赖。
  • 解决扫描包问题:@EnableFeignClients(basePackages="cn.itcast.feign.clients") 或 clients={UserClient.class}。

七、服务网关 Gateway

1. 为什么需要网关

  • 所有微服务的统一入口。三大功能:请求路由、权限控制、限流。
  • 实现:Gateway(响应式 WebFlux,性能好)与 Zuul(Servlet 阻塞式)。选 Gateway。
  • 架构:请求 → 网关 → 按规则路由到某微服务(带负载均衡)→ 返回。

2. 快速入门

spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice      # lb=负载均衡,后跟服务名
          predicates:
            - Path=/user/**          # 路径匹配

lb://userservice 表示按服务名从注册中心拉列表并负载均衡。

3. 断言工厂(Predicate)

决定请求是否符合路由条件。常用 Path=/user/**;还有 After/Before/Between、Header、Method、Query、RemoteAddr 等十几种。入门掌握 Path 即可。

4. 过滤器

  • 路由过滤器 GatewayFilter(31 种):对请求/响应加工,如 AddRequestHeader、RequestRateLimiter(限流)。
  • 配置在路由下只对该路由生效;写在 default-filters 下对所有路由生效。
spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=Truth, itcast-awesome

5. 全局过滤器 GlobalFilter

  • 自己写代码实现拦截逻辑(登录校验、权限、限流)。实现 GlobalFilter 接口,加 @Order 指定顺序(值越小越先执行)。
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){
    String auth = exchange.getRequest().getQueryParams().getFirst("authorization");
    if("admin".equals(auth)) return chain.filter(exchange);
    exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
    return exchange.getResponse().setComplete();
  }
}
  • 执行顺序:order 值相同则 defaultFilter > 路由过滤器 > GlobalFilter。

6. 跨域(CORS)

浏览器禁止跨域 ajax,网关统一解决:

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedOrigins: ["http://localhost:8090"]
            allowedMethods: ["GET","POST","DELETE","PUT","OPTIONS"]
            allowedHeaders: "*"
            allowCredentials: true
            maxAge: 360000

八、消息队列 RabbitMQ

1. 同步 vs 异步

  • 同步(Feign):实时得结果;缺点:耦合高、性能/吞吐下降、级联失败。
  • 异步(事件模式):发布者发事件到 Broker(中间人),订阅者各自处理。优点:吞吐提升、故障隔离、解耦、流量削峰;缺点:架构复杂、依赖 Broker 可靠。

2. MQ 选型对比

MQ公司语言可用性单机吞吐延迟可靠性
RabbitMQRabbitErlang高一般微秒级高
ActiveMQApacheJava一般差毫秒级一般
RocketMQ阿里Java高高毫秒级高
KafkaApacheScala&Java高非常高毫秒内一般

追求可靠/低延迟选 RabbitMQ;追求吞吐选 RocketMQ/Kafka。

3. RabbitMQ 角色

  • publisher(生产者)、consumer(消费者)、exchange(交换机,路由)、queue(队列,存消息)、virtualHost(虚拟主机,租户隔离)。

4. 五种消息模型

  • 基本队列(HelloWorld):一生产者一队列一消费者。
  • WorkQueue:多个消费者绑同一队列,共同消费("能者多劳"靠 prefetch:1)。
  • 发布/订阅(Pub/Sub):引入 exchange,三类交换机:
    • Fanout:广播,发给所有绑定队列。
    • Direct:按 RoutingKey 精确匹配。
    • Topic:RoutingKey 支持通配符(# 多词,* 一词)。
  • exchange 只转发不存储,无队列绑定则消息丢失。

5. SpringAMQP(企业常用)

  • 封装了 RabbitTemplate,自动声明队列/交换机/绑定,注解式监听。
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

spring:
  rabbitmq:
    host: 192.168.150.101
    port: 5672
    virtual-host: /
    username: itcast
    password: 123321
  • 发送:rabbitTemplate.convertAndSend(queueName, message);
  • 接收:
@RabbitListener(queues = "simple.queue")
public void listen(String msg){ System.out.println("收到:" + msg); }
  • 基于注解声明交换机+队列+绑定(Direct 示例):
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue1"),
    exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),
    key = {"red","blue"}
))
public void listen(String msg){ ... }

6. 消息转换器(★重要)

  • 默认 JDK 序列化:体积大、有安全漏洞、可读性差。
  • 改用 JSON:引入 jackson 依赖,启动类加 Bean:
@Bean
public MessageConverter jsonMessageConverter(){ return new Jackson2JsonMessageConverter(); }
  • 生产者和消费者都要配,否则反序列化失败。

九、Docker 容器化部署

1. Docker 解决什么问题

  • 依赖冲突:把应用 + Libs + Deps + 配置一起打包,放隔离容器运行。
  • 环境差异:镜像含完整运行环境(含系统函数库),仅依赖 Linux 内核,可跨 Linux 系统运行。
  • 优势:启动快、体积小、隔离好、一行命令启停。

2. 与虚拟机区别

  • 虚拟机:模拟硬件+完整 OS,重、慢。
  • Docker:只封装函数库,是系统进程,轻、快。

3. 核心概念

  • 镜像(Image):应用及其依赖、环境、配置打包成的只读文件。
  • 容器(Container):镜像运行起来形成的进程(隔离)。一个镜像可起多个容器。
  • DockerHub / 镜像仓库:托管镜像(如 MySQL、Redis 镜像)。国内有阿里云镜像库。
  • 架构:CS 模式,客户端发指令,服务端(守护进程)管镜像/容器。

4. 常用命令

  • 镜像:docker pull nginx、docker images、docker save -o nginx.tar nginx:latest、docker load -i nginx.tar、docker rmi nginx。
  • 容器:docker run --name mn -p 80:80 -d nginx、docker ps、docker ps -a、docker logs -f mn、docker stop/start/rm、docker exec -it mn bash。
  • 镜像名格式:[repository]:[tag],不写 tag 默认 latest。

5. 数据卷(容器数据管理)

  • 容器与数据耦合难维护 → 用数据卷解耦。
  • 数据卷是宿主机目录的虚拟映射,容器内写操作落到宿主机。
docker volume create html
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
  • 也可直接挂宿主机目录:-v /tmp/mysql/data:/var/lib/mysql。
  • 数据卷模式:耦合低、目录深;目录直挂:耦合高、目录好找。

6. Dockerfile 自定义镜像

  • 文本文件,用指令描述构建过程,每行一层。
  • 第一行必须是 FROM(基础镜像,如 java:8-alpine)。
FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
EXPOSE 8090
ENTRYPOINT java -jar /tmp/app.jar
  • 构建:docker build -t javaweb:1.0 .

7. Docker-Compose 部署微服务集群

  • 用一个 yaml 描述多个容器如何运行,免去手动逐个 docker run。
version: "3.2"
services:
  nacos:
    image: nacos/nacos-server
    environment:
      MODE: standalone
    ports:
      - "8848:8848"
  mysql:
    image: mysql:5.7.25
    environment:
      MYSQL_ROOT_PASSWORD: 123
    volumes:
      - "$PWD/mysql/data:/var/lib/mysql"
  userservice:
    build: ./user-service
  orderservice:
    build: ./order-service
  gateway:
    build: ./gateway
    ports:
      - "10010:10010"
  • 容器间用服务名互联(非 IP)。把微服务配置里的 mysql/nacos 地址改为容器名。
  • 打包:finalName 设为 app,每个微服务 Dockerfile 用 app.jar;部署:docker-compose up -d。

8. 私有镜像仓库

  • 推送前先 tag(加仓库地址前缀):
docker tag nginx:latest 192.168.150.101:8080/nginx:1.0
docker push 192.168.150.101:8080/nginx:1.0
docker pull 192.168.150.101:8080/nginx:1.0

十、分布式搜索引擎 Elasticsearch

1. ES 是什么

  • 开源分布式搜索引擎,负责存储、搜索、分析。底层基于 Lucene(Java 搜索引擎类库)。
  • ELK/Elastic Stack:elasticsearch + kibana(可视化)+ Logstash/Beats(采集)。
  • 与 MySQL 分工:MySQL 管事务型写、保一致性;ES 管海量数据搜索/分析。两者结合 + 数据同步。

2. 倒排索引(核心原理)

  • 正向索引:按 id 找文档,但按字段模糊查只能全表扫描。
  • 倒排索引:文档分词得到词条 → 建"词条→文档id"索引。搜索时先分词,拿词条查倒排索引得文档 id,再取文档。速度极快,无需全表扫。
  • 优点:模糊/分词搜索快;缺点:只能按词条建索引,不能按字段排序。

3. ES 概念 vs MySQL

MySQLES说明
TableIndex索引=文档集合(类似表)
RowDocument文档=一条 JSON 数据
ColumnField字段
SchemaMapping映射=字段约束
SQLDSLJSON 风格查询语句

4. 索引库与文档操作(DSL)

  • 创建索引库(含 mapping):
PUT /hotel
{
  "mappings": {
    "properties": {
      "name": { "type": "text", "analyzer": "ik_max_word", "copy_to": "all" },
      "brand": { "type": "keyword", "copy_to": "all" },
      "price": { "type": "integer" },
      "location": { "type": "geo_point" },
      "all": { "type": "text", "analyzer": "ik_max_word" }
    }
  }
}
  • mapping 关键属性:type(text 分词 / keyword 精确 / 数值 / boolean / date / object / geo_point)、index(是否索引)、analyzer、copy_to(合并到 all 字段方便单字段搜)。
  • 索引库一旦创建无法改 mapping,只能加新字段:PUT /索引库/_mapping。
  • 文档 CRUD:
    • 新增:POST /索引库/_doc/文档id {json}
    • 查询:GET /索引库/_doc/id
    • 删除:DELETE /索引库/_doc/id
    • 全量改:PUT /索引库/_doc/id {json}(先删后增)
    • 增量改:POST /索引库/_update/id {"doc":{字段}}

5. 分词器

  • IK 分词器:ik_smart(粗粒度)、ik_max_word(细粒度)。创建倒排索引和搜索时都会分词。
  • 可扩展/停用词条:改 IKAnalyzer.cfg.xml。

6. DSL 查询分类

  • 查询所有:match_all。
  • 全文检索:match(单字段)、multi_match(多字段),走分词+倒排匹配。建议用 copy_to+单字段 all 查询,性能更好。
  • 精确查询:term(词条精确,不分词)、range(范围,如价格)。用于 keyword/数值/日期/布尔。
  • 地理查询:geo_distance(附近 N 公里)、geo_bounding_box(矩形)。
  • 复合查询:bool(must 与/参与算分、should 或、must_not 非/不算分、filter 必须/不算分)、function_score(控制算分排名)。
  • 查询 JSON 结构:query + from/size(分页)+ sort(排序)+ highlight(高亮)。
  • 排序:keyword/数值/日期可排;地理用 _geo_distance。
  • 分页:from+size 支持随机翻页但有 10000 上限(深度分页问题);search_after 适合向下滚动翻页。
  • 高亮:必须配合全文检索查询,给命中词加 <em> 标签。

7. RestHighLevelClient(Java 操作 ES)

  • 步骤:初始化 RestHighLevelClient → 建 XxxRequest(Index/Get/Update/Delete/Bulk/Search)→ 准备参数(DSL)→ 发请求 → 解析结果。
  • 查询解析:从外到内 SearchHits → getTotalHits().value(总数)→ getHits()(文档数组)→ getSourceAsString() 反序列化为对象。
  • 高亮结果在 hit.getHighlightFields(),需替换原字段。

8. 数据聚合(aggregations)

  • 桶(Bucket)聚合:分组,如 terms 按品牌分组、date_histogram 按日期。
  • 度量(Metric)聚合:计算值,如 avg/max/min/stats。可嵌套在桶内对每个组算。
  • aggs 与 query 同级;query 限定聚合范围;size:0 只返回聚合结果不含文档。
  • 参加聚合的字段必须是 keyword/日期/数值/布尔。

9. 自动补全(supplement/suggest)

  • 字段类型必须是 completion;用 Completion Suggester 匹配以输入开头的词条。
  • 拼音补全:装 pinyin 分词器 + 自定义 analyzer(ik + pinyin filter),搜索时用 ik_smart 避免同音字干扰。

10. 数据同步(ES 与 MySQL)

三种方案:

  • 同步调用:业务改库后直接调 ES 接口。简单但耦合高。
  • 异步通知(推荐入门):改库后发 MQ 消息,ES 端监听并更新。低耦合,依赖 MQ 可靠。
  • 监听 binlog(canal):完全解耦,但增加数据库负担、实现复杂。

11. ES 集群(分布式核心)

  • 解决:海量存储(分片 shard 拆分到多节点)、单点故障(副本 replica 备份)。
  • 概念:cluster(同名节点组)、node、shard(主分片)、replica(副本分片)。
  • 节点职责分离:master(选主/管理)、data(数据 CRUD)、coordinator(路由/汇总)。生产建议分离。
  • 脑裂:节点失联导致出现多个 master。解决:选票需 > (eligible节点+1)/2,eligible 节点数取奇数(如 3)。ES7 后默认配置,一般不发生。
  • 分布式存储:对文档 id 做 hash 决定落哪个分片(故分片数创建后不可改)。
  • 分布式查询:scatter phase(分发到各分片)+ gather phase(汇总结果)。
  • 故障转移:master 监控节点,宕机则把分片迁移到其它节点保数据安全。

十一、Redis 缓存 (★重要 之前学过)

1. Redis 是什么

  • 基于内存的键值(key-value)数据库,单线程模型但极快(十万级 QPS),常用于缓存、分布式锁、会话存储、计数器、消息队列(轻量)。
  • 数据持久化:RDB(快照)、AOF(日志);生产常主从+哨兵或 Cluster 集群。

2. 常用数据类型

  • String:字符串/计数(incr),最常用。
  • Hash:对象属性(用户信息)。
  • List:队列、最新列表。
  • Set/ZSet:去重集合 / 有序集合(排行榜、延迟队列)。

3. Spring Boot 整合

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

@Autowired
private StringRedisTemplate redisTemplate; // 默认已配 JDK 序列化,建议改 JSON

// 常用
redisTemplate.opsForValue().set("key", "val", 30, TimeUnit.MINUTES);
String v = redisTemplate.opsForValue().get("key");
  • 缓存注解(Spring Cache):@EnableCaching + @Cacheable/@CachePut/@CacheEvict,简化缓存读写。

4. 典型缓存问题与应对(重要)

  • 缓存穿透:查不存在的数据,绕过缓存打库。→ 缓存空值、布隆过滤器。
  • 缓存击穿:热点 key 过期瞬间大量请求打库。→ 互斥锁、逻辑过期。
  • 缓存雪崩:大量 key 同时过期/Redis 宕机。→ 过期时间加随机值、Redis 高可用集群。

5. 与微服务关系

  • 网关/服务间共享会话、限流计数、热点数据缓存都依赖 Redis。
  • 与 ES 定位不同:Redis 是内存 KV(快、容量小),ES 是搜索分析引擎(磁盘、海量)。

十二、分布式入门

  1. 服务治理:注册中心(Nacos)解决"服务在哪、谁健康";配置中心统一配置+热更新。
  2. 远程调用:Feign 声明式调用 + 连接池优化;Ribbon 做客户端负载均衡。
  3. 流量入口:Gateway 统一路由、鉴权、限流、跨域。
  4. 异步解耦:RabbitMQ 用 Broker 解耦服务,交换机路由消息,JSON 序列化。
  5. 部署运维:Docker 镜像+容器+数据卷,Compose 一键编排微服务集群。
  6. 搜索分析:Elasticsearch 倒排索引+DSL+聚合,MySQL 与 ES 通过 MQ/binlog 同步。
  7. 缓存加速:Redis 扛热点读、共享状态,注意穿透/击穿/雪崩。
  8. 高可用:Nacos 集群、ES 分片+副本+故障转移、Redis 主从/Cluster,都是"分布式"的基础保障。

微服务入门知识总结

  1. 懂单体→分布式→微服务概念,跑通 SpringCloud 父子工程。
  2. 注册中心 Nacos → 配置中心 → Feign → Gateway,搭一个多服务可调用、可路由的小系统。
  3. 引入 RabbitMQ 做异步解耦(如下单后发消息)。
  4. 用 Docker + Compose 把整套服务容器化部署。
  5. 接入 Elasticsearch 做商品/酒店搜索,理解倒排索引与 DSL。
  6. 用 Redis 做缓存,补上分布式缓存与高可用认知。

重点记住:微服务核心是"拆得开、找得到、调得动、挂不了"。
Nacos 管注册配置,Feign/Gateway 管调用入口,MQ 管异步,Docker 管部署,ES 管搜索,Redis 管缓存。

更多推荐