Java学习指南
  • Java 编程的逻辑
  • Java进阶
  • Java FrameWorks
  • 了解 USB Type-A,B,C 三大标准接口
  • 深入浅出DDD
  • 重构:改善既有代码的设计
  • 面试大纲
  • 云原生
    • 什么是无服务器(what is serverless)?
  • 博客
    • 深入分析Log4j 漏洞
  • 博客
    • Serverless之快速搭建Spring Boot应用
  • 博客
    • 使用 Prometheus + Grafana + Spring Boot Actuator 监控应用
  • 博客
    • 使用 Prometheus + Grafana 监控 MySQL
  • 博客
    • 使用Github Actions + Docker 部署Spring Boot应用
  • 博客
    • Redis分布式锁之Redisson的原理和实践
  • 博客
    • 数据库中的树结构应该怎样去设计
  • 学习&成长
    • 如何成为技术大牛
  • 开发工具
    • Git Commit Message Guidelines
  • 开发工具
    • git命名大全
  • 开发工具
    • Gradle vs Maven Comparison
  • 开发工具
    • Swagger2常用注解及其说明
  • 开发工具
    • 简明 VIM 练级攻略
  • 微服务
    • 十大微服务设计模式和原则
  • 微服务
    • 微服务下的身份认证和令牌管理
  • 微服务
    • 微服务坏味道之循环依赖
  • 设计模式
    • 设计模式 - JDK中的设计模式
  • 设计模式
    • 设计模式 - Java三种代理模式
  • 设计模式
    • 设计模式 - 六大设计原则
  • 设计模式
    • 设计模式 - 单例模式
  • 设计模式
    • 设计模式 - 命名模式
  • 设计模式
    • 设计模式 - 备忘录模式
  • 设计模式
    • 设计模式 - 概览
  • 设计模式
    • 设计模式 - 没用的设计模式
  • 质量&效率
    • Homebrew 替换国内镜像源
  • 质量&效率
    • 工作中如何做好技术积累
  • Java FrameWorks
    • Logback
      • 自定义 logback 日志过滤器
  • Java FrameWorks
    • Mybatis
      • MyBatis(十三) - 整合Spring
  • Java FrameWorks
    • Mybatis
      • MyBatis(十二) - 一些API
  • Java FrameWorks
    • Mybatis
      • Mybatis(一) - 概述
  • Java FrameWorks
    • Mybatis
      • Mybatis(七) - 结果集的封装与映射
  • Java FrameWorks
    • Mybatis
      • Mybatis(三) - mapper.xml及其加载机制
  • Java FrameWorks
    • Mybatis
      • Mybatis(九) - 事务
  • Java FrameWorks
    • Mybatis
      • Mybatis(二) - 全局配置文件及其加载机制
  • Java FrameWorks
    • Mybatis
      • Mybatis(五) - SqlSession执行流程
  • Java FrameWorks
    • Mybatis
      • Mybatis(八) - 缓存
  • Java FrameWorks
    • Mybatis
      • Mybatis(六) - 动态SQL的参数绑定与执行
  • Java FrameWorks
    • Mybatis
      • Mybatis(十) - 插件
  • Java FrameWorks
    • Mybatis
      • Mybatis(十一) - 日志
  • Java FrameWorks
    • Mybatis
      • Mybatis(四) - Mapper接口解析
  • Java FrameWorks
    • Netty
      • Netty 可靠性分析
  • Java FrameWorks
    • Netty
      • Netty - Netty 线程模型
  • Java FrameWorks
    • Netty
      • Netty堆外内存泄露排查盛宴
  • Java FrameWorks
    • Netty
      • Netty高级 - 高性能之道
  • Java FrameWorks
    • Shiro
      • Shiro + JWT + Spring Boot Restful 简易教程
  • Java FrameWorks
    • Shiro
      • 非常详尽的 Shiro 架构解析!
  • Java FrameWorks
    • Spring
      • Spring AOP 使用介绍,从前世到今生
  • Java FrameWorks
    • Spring
      • Spring AOP 源码解析
  • Java FrameWorks
    • Spring
      • Spring Event 实现原理
  • Java FrameWorks
    • Spring
      • Spring Events
  • Java FrameWorks
    • Spring
      • Spring IOC容器源码分析
  • Java FrameWorks
    • Spring
      • Spring Integration简介
  • Java FrameWorks
    • Spring
      • Spring MVC 框架中拦截器 Interceptor 的使用方法
  • Java FrameWorks
    • Spring
      • Spring bean 解析、注册、实例化流程源码剖析
  • Java FrameWorks
    • Spring
      • Spring validation中@NotNull、@NotEmpty、@NotBlank的区别
  • Java FrameWorks
    • Spring
      • Spring 如何解决循环依赖?
  • Java FrameWorks
    • Spring
      • Spring 异步实现原理与实战分享
  • Java FrameWorks
    • Spring
      • Spring中的“for update”问题
  • Java FrameWorks
    • Spring
      • Spring中的设计模式
  • Java FrameWorks
    • Spring
      • Spring事务失效的 8 大原因
  • Java FrameWorks
    • Spring
      • Spring事务管理详解
  • Java FrameWorks
    • Spring
      • Spring计时器StopWatch使用
  • Java FrameWorks
    • Spring
      • 详述 Spring MVC 框架中拦截器 Interceptor 的使用方法
  • Java FrameWorks
    • Spring
      • 透彻的掌握 Spring 中@transactional 的使用
  • Java
    • Java IO&NIO&AIO
      • Java IO - BIO 详解
  • Java
    • Java IO&NIO&AIO
      • Java NIO - IO多路复用详解
  • Java
    • Java IO&NIO&AIO
      • Java N(A)IO - Netty
  • Java
    • Java IO&NIO&AIO
      • Java IO - Unix IO模型
  • Java
    • Java IO&NIO&AIO
      • Java IO - 分类
  • Java
    • Java IO&NIO&AIO
      • Java NIO - 基础详解
  • Java
    • Java IO&NIO&AIO
      • Java IO - 常见类使用
  • Java
    • Java IO&NIO&AIO
      • Java AIO - 异步IO详解
  • Java
    • Java IO&NIO&AIO
      • Java IO概述
  • Java
    • Java IO&NIO&AIO
      • Java IO - 设计模式
  • Java
    • Java IO&NIO&AIO
      • Java NIO - 零拷贝实现
  • Java
    • Java JVM
      • JVM 优化经验总结
  • Java
    • Java JVM
      • JVM 内存结构
  • Java
    • Java JVM
      • JVM参数设置
  • Java
    • Java JVM
      • Java 内存模型
  • Java
    • Java JVM
      • 从实际案例聊聊Java应用的GC优化
  • Java
    • Java JVM
      • Java 垃圾回收器G1详解
  • Java
    • Java JVM
      • 垃圾回收器Shenandoah GC详解
  • Java
    • Java JVM
      • 垃圾回收器ZGC详解
  • Java
    • Java JVM
      • 垃圾回收基础
  • Java
    • Java JVM
      • 如何优化Java GC
  • Java
    • Java JVM
      • 类加载机制
  • Java
    • Java JVM
      • 类字节码详解
  • Java
    • Java 基础
      • Java hashCode() 和 equals()
  • Java
    • Java 基础
      • Java 基础 - Java native方法以及JNI实践
  • Java
    • Java 基础
      • Java serialVersionUID 有什么作用?
  • Java
    • Java 基础
      • Java 泛型的类型擦除
  • Java
    • Java 基础
      • Java 基础 - Unsafe类解析
  • Java
    • Java 基础
      • Difference Between Statement and PreparedStatement
  • Java
    • Java 基础
      • Java 基础 - SPI机制详解
  • Java
    • Java 基础
      • Java 基础 - final
  • Java
    • Java 基础
      • Java中static关键字详解
  • Java
    • Java 基础
      • 为什么说Java中只有值传递?
  • Java
    • Java 基础
      • Java 基础 - 即时编译器原理解析及实践
  • Java
    • Java 基础
      • Java 基础 - 反射
  • Java
    • Java 基础
      • Java多态的面试题
  • Java
    • Java 基础
      • Java 基础 - 异常机制详解
  • Java
    • Java 基础
      • 为什么要有抽象类?
  • Java
    • Java 基础
      • 接口的本质
  • Java
    • Java 基础
      • Java 基础 - 枚举
  • Java
    • Java 基础
      • Java 基础 - 泛型机制详解
  • Java
    • Java 基础
      • Java 基础 - 注解机制详解
  • Java
    • Java 基础
      • 为什么 String hashCode 方法选择数字31作为乘子
  • Java
    • Java 并发
      • Java 并发 - 14个Java并发容器
  • Java
    • Java 并发
      • Java 并发 - AQS
  • Java
    • Java 并发
      • Java 并发 - BlockingQueue
  • Java
    • Java 并发
      • Java 并发 - CAS
  • Java
    • Java 并发
      • Java 并发 - Condition接口
  • Java
    • Java 并发
      • Java 并发 - CopyOnWriteArrayList
  • Java
    • Java 并发
      • Java 并发 - CountDownLatch、CyclicBarrier和Phaser对比
  • Java
    • Java 并发
      • Java 并发 - Fork&Join框架
  • Java
    • Java 并发
      • Java 并发 - Java CompletableFuture 详解
  • Java
    • Java 并发
      • Java 并发 - Java 线程池
  • Java
    • Java 并发
      • Java 并发 - Lock接口
  • Java
    • Java 并发
      • Java 并发 - ReentrantLock
  • Java
    • Java 并发
      • Java 并发 - ReentrantReadWriteLock
  • Java
    • Java 并发
      • Java 并发 - Synchronized
  • Java
    • Java 并发
      • Java 并发 - ThreadLocal 内存泄漏问题
  • Java
    • Java 并发
      • Java 并发 - ThreadLocal
  • Java
    • Java 并发
      • Java 并发 - Volatile
  • Java
    • Java 并发
      • Java 并发 - 从ReentrantLock的实现看AQS的原理及应用
  • Java
    • Java 并发
      • Java 并发 - 公平锁和非公平锁
  • Java
    • Java 并发
      • Java 并发 - 内存模型
  • Java
    • Java 并发
      • Java 并发 - 原子类
  • Java
    • Java 并发
      • Java 并发 - 如何确保三个线程顺序执行?
  • Java
    • Java 并发
      • Java 并发 - 锁
  • Java
    • Java 的新特性
      • Java 10 新特性概述
  • Java
    • Java 的新特性
      • Java 11 新特性概述
  • Java
    • Java 的新特性
      • Java 12 新特性概述
  • Java
    • Java 的新特性
      • Java 13 新特性概述
  • Java
    • Java 的新特性
      • Java 14 新特性概述
  • Java
    • Java 的新特性
      • Java 15 新特性概述
  • Java
    • Java 的新特性
      • Java 8的新特性
  • Java
    • Java 的新特性
      • Java 9 新特性概述
  • Java
    • Java 调试排错
      • 调试排错 - Java Debug Interface(JDI)详解
  • Java
    • Java 调试排错
      • 调试排错 - CPU 100% 排查优化实践
  • Java
    • Java 调试排错
      • 调试排错 - Java Heap Dump分析
  • Java
    • Java 调试排错
      • 调试排错 - Java Thread Dump分析
  • Java
    • Java 调试排错
      • 调试排错 - Java动态调试技术原理
  • Java
    • Java 调试排错
      • 调试排错 - Java应用在线调试Arthas
  • Java
    • Java 调试排错
      • 调试排错 - Java问题排查:工具单
  • Java
    • Java 调试排错
      • 调试排错 - 内存溢出与内存泄漏
  • Java
    • Java 调试排错
      • 调试排错 - 在线分析GC日志的网站GCeasy
  • Java
    • Java 调试排错
      • 调试排错 - 常见的GC问题分析与解决
  • Java
    • Java 集合
      • Java 集合 - ArrayList
  • Java
    • Java 集合
      • Java 集合 - HashMap 和 ConcurrentHashMap
  • Java
    • Java 集合
      • Java 集合 - HashMap的死循环问题
  • Java
    • Java 集合
      • Java 集合 - LinkedHashSet&Map
  • Java
    • Java 集合
      • Java 集合 - LinkedList
  • Java
    • Java 集合
      • Java 集合 - PriorityQueue
  • Java
    • Java 集合
      • Java 集合 - Stack & Queue
  • Java
    • Java 集合
      • Java 集合 - TreeSet & TreeMap
  • Java
    • Java 集合
      • Java 集合 - WeakHashMap
  • Java
    • Java 集合
      • Java 集合 - 为什么HashMap的容量是2的幂次方
  • Java
    • Java 集合
      • Java 集合 - 概览
  • Java
    • Java 集合
      • Java 集合 - 高性能队列Disruptor详解
  • 分布式
    • RPC
      • ⭐️RPC - Dubbo&hsf&Spring cloud的区别
  • 分布式
    • RPC
      • ⭐️RPC - Dubbo的架构原理
  • 分布式
    • RPC
      • ⭐️RPC - HSF的原理分析
  • 分布式
    • RPC
      • ⭐️RPC - 你应该知道的RPC原理
  • 分布式
    • RPC
      • ⭐️RPC - 动态代理
  • 分布式
    • RPC
      • 深入理解 RPC 之协议篇
  • 分布式
    • RPC
      • RPC - 序列化和反序列化
  • 分布式
    • RPC
      • ⭐️RPC - 服务注册与发现
  • 分布式
    • RPC
      • RPC - 核心原理
  • 分布式
    • RPC
      • ⭐️RPC - 框架对比
  • 分布式
    • RPC
      • ⭐️RPC - 网络通信
  • 分布式
    • 分布式事务
      • 分布式事务 Seata TCC 模式深度解析
  • 分布式
    • 分布式事务
      • 分布式事务的实现原理
  • 分布式
    • 分布式事务
      • 常用的分布式事务解决方案
  • 分布式
    • 分布式事务
      • 手写实现基于消息队列的分布式事务框架
  • 分布式
    • 分布式算法
      • CAP 定理的含义
  • 分布式
    • 分布式算法
      • Paxos和Raft比较
  • 分布式
    • 分布式算法
      • 分布式一致性与共识算法
  • 分布式
    • 分布式锁
      • ⭐️分布式锁的原理及实现方式
  • 分布式
    • 搜索引擎
      • ElasticSearch与SpringBoot的集成与JPA方法的使用
  • 分布式
    • 搜索引擎
      • 全文搜索引擎 Elasticsearch 入门教程
  • 分布式
    • 搜索引擎
      • 十分钟学会使用 Elasticsearch 优雅搭建自己的搜索系统
  • 分布式
    • 搜索引擎
      • 腾讯万亿级 Elasticsearch 技术解密
  • 分布式
    • 日志系统
      • Grafana Loki 简明教程
  • 分布式
    • 日志系统
      • 分布式系统中如何优雅地追踪日志
  • 分布式
    • 日志系统
      • 如何优雅地记录操作日志?
  • 分布式
    • 日志系统
      • 日志收集组件—Flume、Logstash、Filebeat对比
  • 分布式
    • 日志系统
      • 集中式日志系统 ELK 协议栈详解
  • 分布式
    • 消息队列
      • 消息队列 - Kafka
  • 分布式
    • 消息队列
      • 消息队列 - Kafka、RabbitMQ、RocketMQ等消息中间件的对比
  • 分布式
    • 消息队列
      • 消息队列之 RabbitMQ
  • 分布式
    • 消息队列
      • 消息队列 - 使用docker-compose构建kafka集群
  • 分布式
    • 消息队列
      • 消息队列 - 分布式系统与消息的投递
  • 分布式
    • 消息队列
      • 消息队列 - 如何保证消息的可靠性传输
  • 分布式
    • 消息队列
      • 消息队列 - 如何保证消息的顺序性
  • 分布式
    • 消息队列
      • 消息队列 - 如何保证消息队列的高可用
  • 分布式
    • 消息队列
      • 消息队列 - 消息队列设计精要
  • 分布式
    • 监控系统
      • 深度剖析开源分布式监控CAT
  • 大数据
    • Flink
      • Flink架构与核心组件
  • 微服务
    • Dubbo
      • 基于dubbo的分布式应用中的统一异常处理
  • 微服务
    • Dubbo
      • Vim快捷键
  • 微服务
    • Service Mesh
      • Istio 是什么?
  • 微服务
    • Service Mesh
      • OCTO 2.0:美团基于Service Mesh的服务治理系统详解
  • 微服务
    • Service Mesh
      • Service Mesh是什么?
  • 微服务
    • Service Mesh
      • Spring Cloud向Service Mesh迁移
  • 微服务
    • Service Mesh
      • 数据挖掘算法
  • 微服务
    • Service Mesh
      • Seata Saga 模式
  • 微服务
    • Spring Cloud
      • Seata TCC 模式
  • 微服务
    • Spring Cloud
      • Spring Cloud Config
  • 微服务
    • Spring Cloud
      • Seata AT 模式
  • 微服务
    • Spring Cloud
      • Spring Cloud Gateway
  • 微服务
    • Spring Cloud
      • Spring Cloud OpenFeign 的核心原理
  • 微服务
    • Spring Cloud
      • Seata XA 模式
  • 数据库
    • Database Version Control
      • Liquibase vs. Flyway
  • 数据库
    • Database Version Control
      • Six reasons to version control your database
  • 数据库
    • MySQL
      • How Sharding Works
  • 数据库
    • MySQL
      • MySQL InnoDB中各种SQL语句加锁分析
  • 数据库
    • MySQL
      • MySQL 事务隔离级别和锁
  • 数据库
    • MySQL
      • MySQL 索引性能分析概要
  • 数据库
    • MySQL
      • MySQL 索引设计概要
  • 数据库
    • MySQL
      • MySQL出现Waiting for table metadata lock的原因以及解决方法
  • 数据库
    • MySQL
      • MySQL的Limit性能问题
  • 数据库
    • MySQL
      • MySQL索引优化explain
  • 数据库
    • MySQL
      • MySQL索引背后的数据结构及算法原理
  • 数据库
    • MySQL
      • MySQL行转列、列转行问题
  • 数据库
    • MySQL
      • 一条SQL更新语句是如何执行的?
  • 数据库
    • MySQL
      • 一条SQL查询语句是如何执行的?
  • 数据库
    • MySQL
      • 为什么 MySQL 使用 B+ 树
  • 数据库
    • MySQL
      • 为什么 MySQL 的自增主键不单调也不连续
  • 数据库
    • MySQL
      • 为什么我的MySQL会“抖”一下?
  • 数据库
    • MySQL
      • 为什么数据库不应该使用外键
  • 数据库
    • MySQL
      • 为什么数据库会丢失数据
  • 数据库
    • MySQL
      • 事务的可重复读的能力是怎么实现的?
  • 数据库
    • MySQL
      • 大众点评订单系统分库分表实践
  • 数据库
    • MySQL
      • 如何保证缓存与数据库双写时的数据一致性?
  • 数据库
    • MySQL
      • 浅谈数据库并发控制 - 锁和 MVCC
  • 数据库
    • MySQL
      • 深入浅出MySQL 中事务的实现
  • 数据库
    • MySQL
      • 浅入浅出MySQL 和 InnoDB
  • 数据库
    • PostgreSQL
      • PostgreSQL upsert功能(insert on conflict do)的用法
  • 数据库
    • Redis
      • Redis GEO & 实现原理深度分析
  • 数据库
    • Redis
      • Redis 和 I/O 多路复用
  • 数据库
    • Redis
      • Redis分布式锁
  • 数据库
    • Redis
      • Redis实现分布式锁中的“坑”
  • 数据库
    • Redis
      • Redis总结
  • 数据库
    • Redis
      • 史上最全Redis高可用技术解决方案大全
  • 数据库
    • Redis
      • Redlock:Redis分布式锁最牛逼的实现
  • 数据库
    • Redis
      • 为什么 Redis 选择单线程模型
  • 数据库
    • TiDB
      • 新一代数据库TiDB在美团的实践
  • 数据库
    • 数据仓库
      • 实时数仓在有赞的实践
  • 数据库
    • 数据库原理
      • OLTP与OLAP的关系是什么?
  • 数据库
    • 数据库原理
      • 为什么 OLAP 需要列式存储
  • 系统设计
    • DDD
      • Domain Primitive
  • 系统设计
    • DDD
      • Repository模式
  • 系统设计
    • DDD
      • 应用架构
  • 系统设计
    • DDD
      • 聊聊如何避免写流水账代码
  • 系统设计
    • DDD
      • 领域层设计规范
  • 系统设计
    • DDD
      • 从三明治到六边形
  • 系统设计
    • DDD
      • 阿里盒马领域驱动设计实践
  • 系统设计
    • DDD
      • 领域驱动设计(DDD)编码实践
  • 系统设计
    • DDD
      • 领域驱动设计在互联网业务开发中的实践
  • 系统设计
    • 基础架构
      • 容错,高可用和灾备
  • 系统设计
    • 数据聚合
      • GraphQL及元数据驱动架构在后端BFF中的实践
  • 系统设计
    • 数据聚合
      • 高效研发-闲鱼在数据聚合上的探索与实践
  • 系统设计
    • 服务安全
      • JSON Web Token 入门教程
  • 系统设计
    • 服务安全
      • 你还在用JWT做身份认证嘛?
  • 系统设计
    • 服务安全
      • 凭证(Credentials)
  • 系统设计
    • 服务安全
      • 授权(Authorization)
  • 系统设计
    • 服务安全
      • 理解OAuth2.0
  • 系统设计
    • 服务安全
      • 认证(Authentication)
  • 系统设计
    • 架构案例
      • 微信 Android 客户端架构演进之路
  • 系统设计
    • 高可用架构
      • 业务高可用的保障:异地多活架构
  • 计算机基础
    • 字符编码
      • Base64原理解析
  • 计算机基础
    • 字符编码
      • 字符编码笔记:ASCII,Unicode 和 UTF-8
  • 计算机基础
    • 操作系统
      • 为什么 CPU 访问硬盘很慢
  • 计算机基础
    • 操作系统
      • 为什么 HTTPS 需要 7 次握手以及 9 倍时延
  • 计算机基础
    • 操作系统
      • 为什么 Linux 默认页大小是 4KB
  • 计算机基础
    • 操作系统
      • 磁盘IO那些事
  • 计算机基础
    • 操作系统
      • 虚拟机的3种网络模式
  • 计算机基础
    • 服务器
      • mac终端bash、zsh、oh-my-zsh最实用教程
  • 计算机基础
    • 服务器
      • Nginx强制跳转Https
  • 计算机基础
    • 服务器
      • curl 的用法指南
  • 计算机基础
    • 网络安全
      • 如何设计一个安全的对外接口?
  • 计算机基础
    • 网络安全
      • 浅谈常见的七种加密算法及实现
  • 计算机基础
    • 网络编程
      • MQTT - The Standard for IoT Messaging
  • 计算机基础
    • 网络编程
      • 两万字长文 50+ 张趣图带你领悟网络编程的内功心法
  • 计算机基础
    • 网络编程
      • 为什么 TCP 协议有 TIME_WAIT 状态
  • 计算机基础
    • 网络编程
      • 为什么 TCP 协议有性能问题
  • 计算机基础
    • 网络编程
      • 为什么 TCP 协议有粘包问题
  • 计算机基础
    • 网络编程
      • 为什么 TCP 建立连接需要三次握手
  • 计算机基础
    • 网络编程
      • 为什么 TCP/IP 协议会拆分数据
  • 计算机基础
    • 网络编程
      • 使用 OAuth 2 和 JWT 为微服务提供安全保障
  • 计算机基础
    • 网络编程
      • 四种常见的 POST 提交数据方式
  • 计算机基础
    • 网络编程
      • 有赞TCP网络编程最佳实践
  • 计算机基础
    • 网络编程
      • 看完这篇HTTP,跟面试官扯皮就没问题了
  • 计算机基础
    • 网络编程
      • 详细解析 HTTP 与 HTTPS 的区别
  • 质量&效率
    • 快捷键
      • Idea快捷键(Mac版)
  • 质量&效率
    • 快捷键
      • Shell快捷键
  • 质量&效率
    • 快捷键
      • conduit
  • 质量&效率
    • 敏捷开发
      • Scrum的3种角色
  • 质量&效率
    • 敏捷开发
      • Scrum的4种会议
  • 质量&效率
    • 敏捷开发
      • ThoughtWorks的敏捷开发
  • 质量&效率
    • 敏捷开发
      • 敏捷开发入门教程
  • 运维&测试
    • Docker
      • Docker (容器) 的原理
  • 运维&测试
    • Docker
      • Docker Compose:链接外部容器的几种方式
  • 运维&测试
    • Docker
      • Docker 入门教程
  • 运维&测试
    • Docker
      • Docker 核心技术与实现原理
  • 运维&测试
    • Docker
      • Dockerfile 最佳实践
  • 运维&测试
    • Docker
      • Docker开启Remote API 访问 2375端口
  • 运维&测试
    • Docker
      • Watchtower - 自动更新 Docker 镜像与容器
  • 运维&测试
    • Kubernetes
      • Kubernetes 介绍
  • 运维&测试
    • Kubernetes
      • Kubernetes 在有赞的实践
  • 运维&测试
    • Kubernetes
      • Kubernetes 学习路径
  • 运维&测试
    • Kubernetes
      • Kubernetes如何改变美团的云基础设施?
  • 运维&测试
    • Kubernetes
      • Kubernetes的三种外部访问方式:NodePort、LoadBalancer 和 Ingress
  • 运维&测试
    • Kubernetes
      • 谈 Kubernetes 的架构设计与实现原理
  • 运维&测试
    • 压测
      • 全链路压测平台(Quake)在美团中的实践
  • 运维&测试
    • 测试
      • Cpress - JavaScript End to End Testing Framework
  • 运维&测试
    • 测试
      • 代码覆盖率-JaCoCo
  • 运维&测试
    • 测试
      • 浅谈代码覆盖率
  • 运维&测试
    • 测试
      • 测试中 Fakes、Mocks 以及 Stubs 概念明晰
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP中的Bean是如何被AOP代理的
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP原生动态代理和Cglib动态代理
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP实现方式(xml&注解)
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP是如何收集切面类并封装的
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP概述
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP的底层核心后置处理器
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP的延伸知识
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(一)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(三)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(二)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(五)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(四) - 循环依赖与解决方案
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - 启动引导
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot JarLauncher
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot Web Mvc 自动装配
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot 使用ApplicationListener监听器
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot 声明式事务
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot 嵌入式容器
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot引起的“堆外内存泄漏”排查及经验总结
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot的启动流程
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot自动化配置源码分析
  • Java FrameWorks
    • Spring
      • Spring Boot
        • 如何自定义Spring Boot Starter?
  • Java FrameWorks
    • Spring
      • Spring IOC
        • IOC - 模块装配和条件装配
  • Java FrameWorks
    • Spring
      • Spring IOC
        • IOC - 配置源(xml,注解)
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Environment
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring ApplicationContext
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanDefinition
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanFactory
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanFactoryPostProcessor
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanPostProcessor
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(一) - 概述
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(三) - 实例化阶段
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(二) - BeanDefinition
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(五) - 销毁阶段
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(四) - 初始化阶段
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring ComponentScan
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Events
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC 基础篇
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC 总结
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC 进阶篇
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC容器的生命周期
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Resource
  • Java FrameWorks
    • Spring
      • Spring MVC
        • DispatcherServlet的初始化原理
  • Java FrameWorks
    • Spring
      • Spring MVC
        • DispatcherServlet的核心工作原理
  • Java FrameWorks
    • Spring
      • Spring MVC
        • WebMvc的架构设计与组件功能解析
  • Java FrameWorks
    • Spring
      • Spring Security
        • Spring Boot 2 + Spring Security 5 + JWT 的单页应用 Restful 解决方案
  • Java FrameWorks
    • Spring
      • Spring Security
        • Spring Security Oauth
  • Java FrameWorks
    • Spring
      • Spring Security
        • Spring Security
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • DispatcherHandler的工作原理(传统方式)
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • DispatcherHandler的工作原理(函数式端点)
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • WebFlux的自动装配
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • 快速了解响应式编程与Reactive
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • 快速使用WebFlux
  • 分布式
    • 协调服务
      • Zookeeper
        • Zookeeper - 客户端之 Curator
  • 分布式
    • 协调服务
      • Zookeeper
        • 详解分布式协调服务 ZooKeeper
  • 分布式
    • 协调服务
      • etcd
        • 高可用分布式存储 etcd 的实现原理
  • 数据库
    • Database Version Control
      • Flyway
        • Database Migrations with Flyway
  • 数据库
    • Database Version Control
      • Flyway
        • How Flyway works
  • 数据库
    • Database Version Control
      • Flyway
        • Rolling Back Migrations with Flyway
  • 数据库
    • Database Version Control
      • Flyway
        • The meaning of the concept of checksums
  • 数据库
    • Database Version Control
      • Liquibase
        • Introduction to Liquibase Rollback
  • 数据库
    • Database Version Control
      • Liquibase
        • LiquiBase中文学习指南
  • 数据库
    • Database Version Control
      • Liquibase
        • Use Liquibase to Safely Evolve Your Database Schema
  • 系统设计
    • 流量控制
      • RateLimiter
        • Guava Rate Limiter实现分析
  • 系统设计
    • 流量控制
      • Sentinel
        • Sentinel 与 Hystrix 的对比
  • 系统设计
    • 流量控制
      • Sentinel
        • Sentinel工作主流程
  • 系统设计
    • 流量控制
      • 算法
        • 分布式服务限流实战
  • 系统设计
    • 解决方案
      • 秒杀系统
        • 如何设计一个秒杀系统
  • 系统设计
    • 解决方案
      • 红包系统
        • 微信高并发资金交易系统设计方案--百亿红包背后的技术支撑
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 什么是预排序遍历树算法(MPTT,Modified Preorder Tree Traversal)
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 加密算法
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 推荐系统算法
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • linkerd
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 查找算法
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 缓存淘汰算法中的LRU和LFU
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 负载均衡算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - Paxos算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - Raft算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - Snowflake算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - ZAB算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - 一致性Hash算法
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - Bitmap & Bloom Filter
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - Map & Reduce
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - Trie树/数据库/倒排索引
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 分治/hash/排序
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 双层桶划分
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 外(磁盘文件)排序
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 布隆过滤器
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理算法
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 文本预处理:后缀树(Suffix Tree)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 模式预处理:BM 算法 (Boyer-Moore)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 模式预处理:KMP 算法(Knuth-Morris-Pratt)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 模式预处理:朴素算法(Naive)(暴力破解)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 分支限界算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 分治算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 动态规划算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 回溯算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 贪心算法
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 十大排序算法
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(一)之3种简单排序(选择,冒泡,直接插入)
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(三)之堆排序
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(二)之希尔排序
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(四)之归并排序
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 树的高度和深度
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 红黑树深入剖析及Java实现
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 线性结构 - Hash
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 线性结构 - 数组、链表、栈、队列
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 逻辑结构 - 树
  • 运维&测试
    • 测试
      • Spock
        • Groovy 简明教程
  • 运维&测试
    • 测试
      • Spock
        • Spock 官方文档
  • 运维&测试
    • 测试
      • Spock
        • Spock单元测试框架介绍以及在美团优选的实践
  • 运维&测试
    • 测试
      • TDD
        • TDD 实践 - FizzFuzzWhizz(一)
  • 运维&测试
    • 测试
      • TDD
        • TDD 实践 - FizzFuzzWhizz(三)
  • 运维&测试
    • 测试
      • TDD
        • TDD 实践 - FizzFuzzWhizz(二)
  • 运维&测试
    • 测试
      • TDD
        • 测试驱动开发(TDD)- 原理篇
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Nacos
          • Nacos 服务注册的原理
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Nacos
          • Nacos 配置中心原理分析
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • 服务调用过程
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • Spring Cloud Bus
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • Spring Cloud Consul
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • Spring Cloud Stream
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Sentinel
          • Sentinel 与 Hystrix 的对比
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Sentinel
          • Sentinel
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • How Hystrix Works
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • Hystrix
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • Hystrix原理与实战
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • Spring Cloud Hystrix基本原理
由 GitBook 提供支持
在本页
  • 1. 背景和现状
  • 2. 前期调研测试
  • 2.1 对 TiDB 的定位
  • 2.2 测试
  • 3. 存储生态建设
  • 3.1 业务接入层
  • 3.2 监控报警
  • 3.3 批量部署
  • 3.4 自动化运维平台
  • 3.5 上下游异构数据同步
  • 4. 线上使用磨合
  • 4.1 写入量大、读 QPS 高的离线业务
  • 4.2 在线 OLTP,对响应时间敏感的业务
  • 5. 总结展望

这有帮助吗?

  1. 数据库
  2. TiDB

新一代数据库TiDB在美团的实践

上一页TiDB下一页数据库

最后更新于2年前

这有帮助吗?

转载:

1. 背景和现状

近几年,基于MySQL构建的传统关系型数据库服务,已经很难支撑美团业务的爆发式增长,这就促使我们去探索更合理的数据存储方案和实践新的运维方式。而随着分布式数据库大放异彩,美团DBA团队联合基础架构存储团队,于 2018 年初启动了分布式数据库项目。

2021-03-10-JRHOmR

美团业务线众多,我们根据业务特点及重要程度逐步推进上线,到截稿为止,已经上线了 10 个集群,近 200 个物理节点,大部分是 OLTP 类型的应用,除了上线初期遇到了一些小问题,目前均已稳定运行。初期上线的集群,已经分别服务于配送、出行、闪付、酒旅等业务。虽然 TiDB 的架构分层相对比较清晰,服务也是比较平稳和流畅,但在美团当前的数据量规模和已有稳定的存储体系的基础上,推广新的存储服务体系,需要对周边工具和系统进行一系列改造和适配,从初期探索到整合落地,仍然还需要走很远的路。下面将从以下几个方面分别进行介绍:

  • 从 0 到 1 的突破,重点考虑做哪些事情。

  • 如何规划实施不同业务场景的接入和已有业务的迁移。

  • 上线后遇到的一些典型问题介绍。

  • 后续规划和对未来的展望。

2. 前期调研测试

2.1 对 TiDB 的定位

我们对于 TiDB 的定位,前期在于重点解决 MySQL 的单机性能和容量无法线性和灵活扩展的问题,与 MySQL 形成互补。业界分布式方案很多,我们为何选择了 TiDB 呢?考虑到公司业务规模的快速增长,以及公司内关系数据库以 MySQL 为主的现状,因此我们在调研阶段,对以下技术特性进行了重点考虑:

  • 协议兼容 MySQL:这个是必要项。

  • 可在线扩展:数据通常要有分片,分片要支持分裂和自动迁移,并且迁移过程要尽量对业务无感知。

  • 强一致的分布式事务:事务可以跨分片、跨节点执行,并且强一致。

  • 支持二级索引:为兼容 MySQL 的业务,这个是必须的。

  • 性能:MySQL 的业务特性,高并发的 OLTP 性能必须满足。

  • 跨机房服务:需要保证任何一个机房宕机,服务能自动切换。

  • 跨机房双写:支持跨机房双写是数据库领域一大难题,是我们对分布式数据库的一个重要期待,也是美团下一阶段重要的需求。

业界的一些传统方案虽然支持分片,但无法自动分裂、迁移,不支持分布式事务,还有一些在传统 MySQL 上开发一致性协议的方案,但它无法实现线性扩展,最终我们选择了与我们的需求最为接近的 TiDB。与 MySQL 语法和特性高度兼容,具有灵活的在线扩容缩容特性,支持 ACID 的强一致性事务,可以跨机房部署实现跨机房容灾,支持多节点写入,对业务又能像单机 MySQL 一样使用。

2.2 测试

针对官方声称的以上优点,我们进行了大量的研究、测试和验证。

首先,我们需要知道扩容、Region 分裂转移的细节、Schema 到 KV 的映射、分布式事务的实现原理。而 TiDB 的方案,参考了较多的 Google 论文,我们进行了阅读,这有助于我们理解 TiDB 的存储结构、事务算法、安全性等,包括:

  • Spanner: Google’s Globally-Distributed Database

  • Large-scale Incremental Processing Using Distributed Transactions and Notifications

  • In Search of an Understandable Consensus Algorithm

  • Online, Asynchronous Schema Change in F1

我们也进行了常规的性能和功能测试,用来与 MySQL 的指标进行对比,其中一个比较特别的测试,是证明 3 副本跨机房部署,确实能保证每个机房分布一个副本,从而保证任何一个机房宕机不会导致丢失超过半数副本。我们从以下几个点进行了测试:

  • Raft 扩容时是否支持 Learner 节点,从而保证单机房宕机不会丢失 2⁄3 的副本。

  • TiKV 上的标签优先级是否可靠,保证当机房的机器不平均时,能否保证每个机房的副本数依然是绝对平均的。

  • 实际测试,单机房宕机,TiDB 在高并发下,QPS、响应时间、报错数量,以及最终数据是否有丢失。

  • 手动 Balance 一个 Region 到其他机房,是否会自动回来。

从测试结果来看,一切都符合我们的预期。

3. 存储生态建设

美团的产品线丰富,业务体量也比较大,业务对在线存储的服务质量要求也非常高。因此,从早期做好服务体系的规划非常重要。下面从业务接入层、监控报警、服务部署等维度,来分别介绍一下我们所做的工作。

3.1 业务接入层

当前 MySQL 的业务接入方式主要有两种,DNS 接入和 Zebra 客户端接入。在前期调研阶段,我们选择了 DNS + 负载均衡组件的接入方式,TiDB-Server 节点宕机,15s 可以被负载均衡识别到,简单且有效。业务架构如下图所示:

图 2 业务架构图

后面,我们会逐渐过渡到当前大量使用的 Zebra 接入方式来访问 TiDB,从而保持与访问 MySQL 的方式一致,一方面减少业务改造的成本,另一方面尽量实现从 MySQL 到 TiDB 的透明迁移。

3.2 监控报警

美团目前使用 Mt-Falcon 平台负责监控报警,通过在 Mt-Falcon 上配置不同的插件,可以实现对多种组件的自定义监控。另外也会结合 Puppet 识别不同用户的权限、文件的下发。只要我们编写好插件脚本、需要的文件,装机和权限控制就可以完成了。监控架构如下图所示:

图 3 监控架构图

而 TiDB 有丰富的监控指标,使用流行的 Prometheus + Grafana,一套集群有 700+ 的 Metric。从官方的架构图可以看出,每个组件会推送自己的 Metric 给 PushGateWay,Prometheus 会直接到 PushGateWay 去抓数据。

由于我们需要组件收敛,原生的 TiDB 每个集群一套 Prometheus 的方式不利于监控的汇总、分析、配置,而报警已经在 Mt-Falcon 上实现的比较好了,在 AlertManager 上再造一个也没有必要。因此我们需要想办法把监控和报警汇总到 Mt-Falcon 上面,包括如下几种方式:

  • 方案一:修改源代码,将 Metric 直接推送到 Falcon,由于 Metric 散落在代码的不同位置,而且 TiDB 代码迭代太快,把精力消耗在不停调整监控埋点上不太合适。

  • 方案二:在 PushGateWay 是汇总后的,可以直接抓取,但 PushGateWay 是个单点,不好维护。

  • 方案三:通过各个组件(TiDB、PD、TiKV)的本地 API 直接抓取,优点是组件宕机不会影响其他组件,实现也比较简单。

我们最终选择了方案三。该方案的难点是需要把 Prometheus 的数据格式转化为 Mt-Falcon 可识别的格式,因为 Prometheus 支持 Counter、Gauge、Histogram、Summary 四种数据类型,而 Mt-Falcon 只支持基本的 Counter 和 Gauge,同时 Mt-Falcon 的计算表达式比较少,因此需要在监控脚本中进行转换和计算。

3.3 批量部署

TiDB 使用 Ansible 实现自动化部署。迭代快,是 TiDB 的一个特点,有问题能快速进行解决,但也造成 Ansible 工程、TiDB 版本更新过快,我们对 Ansible 的改动,也只会增加新的代码,不会改动已有的代码。因此线上可能同时需要部署、维护多个版本的集群。如果每个集群一个 Ansible 目录,造成空间的浪费。

我们采用的维护方式是,在中控机中,每个版本一个 Ansible 目录,每个版本中通过不同 inventory 文件来维护。这里需要跟 PingCAP 提出的是,Ansible 只考虑了单集群部署,大量部署会有些麻烦,像一些依赖的配置文件,都不能根据集群单独配置(咨询官方得知,PingCAP 目前正在基于 Cloud TiDB 打造一站式 HTAP 平台,会提供批量部署、多租户等功能,后续会比较好地解决这个问题)。

3.4 自动化运维平台

随着线上集群数量的增加,打造运维平台提上了日程,而美团对 TiDB 和 MySQL 的使用方式基本相同,因此 MySQL 平台上具有的大部分组件,TiDB 平台也需要建设。典型的底层组件和方案:SQL 审核模块、DTS、数据备份方案等。自动化运维平台展示如下图所示:

图 4 自动化运维平台展示图

3.5 上下游异构数据同步

TiDB 是在线存储体系中的一环,它同时也需要融入到公司现有的数据流中,因此需要一些工具来做衔接。PingCAP 官方标配了相关的组件。

公司目前 MySQL 和 Hive 结合的比较重,而 TiDB 要代替 MySQL 的部分功能,需要解决 2 个问题:

  • MySQL to TiDB

    • MySQL 到 TiDB 的迁移,需要解决数据迁移以及增量的实时同步,也就是 DTS,Mydumper + Loader 解决存量数据的同步,官方提供了 DM 工具可以很好的解决增量同步问题。

    • MySQL 大量使用了自增 ID 作为主键。分库分表 MySQL 合并到 TiDB 时,需要解决自增 ID 冲突的问题。这个通过在 TiDB 端去掉自增 ID 建立自己的唯一主键来解决。新版 DM 也提供分表合并过程主键自动处理的功能。

  • Hive to TiDB & TiDB to Hive

    • Hive to TiDB 比较好解决,这体现了 TiDB 和 MySQL 高度兼容的好处,insert 语句可以不用调整,基于 Hive to MySQL 简单改造即可。

    • TiDB to Hive 则需要基于官方 Pump + Drainer 组件,Drainer 可以消费到 Kafka、MySQL、TiDB,我们初步考虑用图 5 中的方案通过使用 Drainer 的 Kafka 输出模式同步到 Hive。

图 5 TiDB to Hive 方案图

4. 线上使用磨合

对于初期上线的业务,我们比较谨慎,基本的原则是:离线业务 -> 非核心业务 -> 核心业务。TiDB 已经发布两年多,且前期经历了大量的测试,我们也深入了解了其它公司的测试和使用情况,可以预期的是 TiDB 上线会比较稳定,但依然遇到了一些小问题。总体来看,在安全性、数据一致性等关键点上没有出现问题。其他一些性能抖动问题,参数调优的问题,也都得到了快速妥善的解决。这里给 PingCAP 的同学点个大大的赞,问题响应速度非常快,与我们美团内部研发的合作也非常融洽。

4.1 写入量大、读 QPS 高的离线业务

我们上线的最大的一个业务,每天有数百 G 的写入量,在前期,我们也遇到了较多的问题。

业务场景:

  • 稳定的写入,每个事务操作 100~200 行不等,每秒 6W 的数据写入。

  • 每天的写入量超过 500G,以后会逐步提量到每天 3T。

  • 每 15 分钟的定时读 Job,5000 QPS(高频量小)。

  • 不定时的查询(低频量大)。

之前使用 MySQL 作为存储,但 MySQL 到达了容量和性能瓶颈,而业务的容量未来会 10 倍的增长。初期调研测试了 ClickHouse,满足了容量的需求,测试发现运行低频 SQL 没有问题,但高频 SQL 的大并发查询无法满足需求,只在 ClickHouse 跑全量的低频 SQL 又会 overkill,最终选择使用 TiDB。

测试期间模拟写入了一天的真实数据,非常稳定,高频低频两种查询也都满足需求,定向优化后 OLAP 的 SQL 比 MySQL 性能提高四倍。但上线后,陆续发现了一些问题,典型的如下:

4.1.1 TiKV 发生 Write Stall

TiKV 底层有 2 个 RocksDB 作为存储。新写的数据写入 L0 层,当 RocksDB 的 L0 层数量达到一定数量,就会发生减速,更高则发生 Stall,用来自我保护。TiKV 的默认配置:

  • level0-slowdown-writes-trigger = 20

  • level0-stop-writes-trigger = 36

遇到过的,发生 L0 文件过多可能的原因有 2 个:

  • 写入量大,Compact 完不成。

  • Snapshot 一直创建不完,导致堆积的副本一下释放,RocksDB-Raft 创建大量的 L0 文件,监控展示如下图所示:

图 6 TiKV 发生 Write Stall 监控展示图

我们通过以下措施,解决了 Write Stall 的问题:

  • 减缓 Raft Log Compact 频率(增大 raft-log-gc-size-limit、raft-log-gc-count-limit)

  • 加快 Snapshot 速度(整体性能、包括硬件性能)

  • max-sub-compactions 调整为 3

  • max-background-jobs 调整为 12

  • level 0 的 3 个 Trigger 调整为 16、32、64

4.1.2 Delete 大量数据,GC 跟不上

现在 TiDB 的 GC 对于每个 kv-instance 是单线程的,当业务删除数据的量非常大时,会导致 GC 速度较慢,很可能 GC 的速度跟不上写入。

目前可以通过增多 TiKV 个数来解决,长期需要靠 GC 改为多线程执行,官方对此已经实现,即将发布。

4.1.3 Insert 响应时间越来越慢

业务上线初期,insert 的响应时间 80 线(Duration 80 By Instance)在 20ms 左右,随着运行时间增加,发现响应时间逐步增加到 200ms+。期间排查了多种可能原因,定位在由于 Region 数量快速上涨,Raftstore 里面要做的事情变多了,而它又是单线程工作,每个 Region 定期都要 heartbeat,带来了性能消耗。tikv-raft propose wait duration 指标持续增长。

解决问题的办法:

  • 临时解决。

  • 增加 Heartbeat 的周期,从 1s 改为 2s,效果比较明显,监控展示如下图所示:

    图 7 insert 响应时间优化前后对比图

  • 彻底解决。

  • 需要减少 Region 个数,Merge 掉空 Region,官方在 2.1 版本中已经实现了 Region Merge 功能,我们在升级到 2.1 后,得到了彻底解决。

  • 另外,等待 Raftstore 改为多线程,能进一步优化。(官方回复相关开发已基本接近尾声,将于 2.1 的下一个版本发布。)

4.1.4 Truncate Table 空间无法完全回收

DBA Truncate 一张大表后,发现 2 个现象,一是空间回收较慢,二是最终也没有完全回收。

  • 由于底层 RocksDB 的机制,很多数据落在 Level 6 上,有可能清不掉。这个需要打开 cdynamic-level-bytes 会优化 Compaction 的策略,提高 Compact 回收空间的速度。

  • 由于 Truncate 使用 delete_files_in_range 接口,发给 TiKV 去删 SST 文件,这里只删除不相交的部分,而之前判断是否相交的粒度是 Region,因此导致了大量 SST 无法及时删除掉。

  • 考虑 Region 独立 SST 可以解决交叉问题,但是随之带来的是磁盘占用问题和 Split 延时问题。

  • 考虑使用 RocksDB 的 DeleteRange 接口,但需要等该接口稳定。

  • 目前最新的 2.1 版本优化为直接使用 DeleteFilesInRange 接口删除整个表占用的空间,然后清理少量残留数据,目前已经解决。

4.1.5 开启 Region Merge 功能

为了解决 region 过多的问题,我们在升级 2.1 版本后,开启了 region merge 功能,但是 TiDB 的响应时间 80 线(Duration 80 By Instance)依然没有恢复到当初,保持在 50ms 左右,排查发现 KV 层返回的响应时间还很快,和最初接近,那么就定位了问题出现在 TiDB 层。研发人员和 PingCAP 定位在产生执行计划时行为和 2.0 版本不一致了,目前已经优化。

4.2 在线 OLTP,对响应时间敏感的业务

除了分析查询量大的离线业务场景,美团还有很多分库分表的场景,虽然业界有很多分库分表的方案,解决了单机性能、存储瓶颈,但是对于业务还是有些不友好的地方:

  • 业务无法友好的执行分布式事务。

  • 跨库的查询,需要在中间层上组合,是比较重的方案。

  • 单库如果容量不足,需要再次拆分,无论怎样做,都很痛苦。

  • 业务需要关注数据分布的规则,即使用了中间层,业务心里还是没底。

因此很多分库分表的业务,以及即将无法在单机承载而正在设计分库分表方案的业务,主动找到了我们,这和我们对于 TiDB 的定位是相符的。这些业务的特点是 SQL 语句小而频繁,对一致性要求高,通常部分数据有时间属性。在测试及上线后也遇到了一些问题,不过目前基本都有了解决办法。

4.2.1 SQL 执行超时后,JDBC 报错

业务偶尔报出 privilege check fail。

是由于业务在 JDBC 设置了 QueryTimeout,SQL 运行超过这个时间,会发行一个 kill query 命令,而 TiDB 执行这个命令需要 Super 权限,业务是没有权限的。其实 kill 自己的查询,并不需要额外的权限,目前已经解决了这个问题:

https://github.com/pingcap/tidb/pull/7003,不再需要 Super 权限,已在 2.0.5 上线。

4.2.2 执行计划偶尔不准

TiDB 的物理优化阶段需要依靠统计信息。在 2.0 版本统计信息的收集从手动执行,优化为在达到一定条件时可以自动触发:

  • 数据修改比例达到 tidb_auto_analyze_ratio。

  • 表一分钟没有变更(目前版本已经去掉这个条件)。

但是在没有达到这些条件之前统计信息是不准的,这样就会导致物理优化出现偏差,在测试阶段(2.0 版本)就出现了这样一个案例:业务数据是有时间属性的,业务的查询有 2 个条件,比如:时间+商家 ID,但每天上午统计信息可能不准,当天的数据已经有了,但统计信息认为没有。这时优化器就会建议使用时间列的索引,但实际上商家 ID 列的索引更优化。这个问题可以通过增加 Hint 解决。

在 2.1 版本对统计信息和执行计划的计算做了大量的优化,也稳定了基于 Query Feedback 更新统计信息,也用于更新直方图和 Count-Min Sketch,非常期待 2.1 的 GA。

5. 总结展望

经过前期的测试、各方的沟通协调,以及近半年对 TiDB 的使用,我们看好 TiDB 的发展,也对未来基于 TiDB 的合作充满信心。

接下来,我们会加速推进 TiDB 在更多业务系统中的使用,同时也将 TiDB 纳入了美团新一代数据库的战略选型中。当前,我们已经全职投入了 3 位 DBA 同学和多位存储计算专家,从底层的存储,中间层的计算,业务层的接入,再到存储方案的选型和布道,进行全方位和更深入的合作。

长期来看,结合美团不断增长的业务规模,我们将与 PingCAP 官方合作打造更强大的生态体系:

  • Titan:Titan 是 TiDB 下一步比较大的动作,也是我们非常期待的下一代存储引擎,它对大 Value 支持会更友好,将解决我们单行大小受限,单机 TiKV 最大支持存储容量的问题,大大提升大规模部署的性价比。

  • Cloud TiDB (Based on Docker & K8s):云计算大势所趋,PingCAP 在这块也布局比较早,今年 8 月份开源了 TiDB Operator,Cloud TiDB 不仅实现了数据库的高度自动化运维,而且基于 Docker 硬件隔离,实现了数据库比较完美的多租户架构。我们和官方同学沟通,目前他们的私有云方案在国内也有重要体量的 POC,这也是美团看重的一个方向。

  • TiDB HTAP Platform:PingCAP 在原有 TiDB Server 计算引擎的基础上,还构建 TiSpark 计算引擎,和他们官方沟通,他们在研发了一个基于列的存储引擎,这样就形成了下层行、列两个存储引擎、上层两个计算引擎的完整混合数据库(HTAP),这个架构不仅大大的节省了核心业务数据在整个公司业务周期里的副本数量,还通过收敛技术栈,节省了大量的人力成本、技术成本、机器成本,同时还解决了困扰多年的 OLAP 的实效性。后面我们也会考虑将一些有实时、准实时的分析查询系统接入 TiDB。

    图 8 TiDB HTAP Platform 整体架构图

  • 后续的物理备份方案,跨机房多写等也是我们接下来逐步推进的场景,总之,我们坚信未来 TiDB 在美团的使用场景会越来越多,发展也会越来越好。

目前,TiDB 在业务层面、技术合作层面都已经在美团扬帆起航,美团点评将携手 PingCAP 开启新一代数据库深度实践、探索之旅。后续,还有美团点评架构存储团队针对 TiDB 源码研究和改进的系列文章,敬请期待。

在立项之初,我们进行了大量解决方案的对比,深入了解了业界的 scale-out(横向扩展)、scale-up(纵向扩展)等解决方案。但考虑到技术架构的前瞻性、发展潜力、社区活跃度以及服务本身与 MySQL 的兼容性,我们最终敲定了基于 数据库进行二次开发的整体方案,并与 PingCAP 官方和开源社区进行深入合作的开发模式。

2021-03-10-Y9Q440
2021-03-10-jdsP5x
2021-03-10-nVrtri
2021-03-10-84qLfL
2021-03-10-XnJp7v
2021-03-10-G6Ppsr
2021-03-10-8uq7ww
TiDB
新一代数据库TiDB在美团的实践