MST

星途 面试题库

面试题:复杂场景下MySQL全文检索的架构设计

现在有一个大型的电商平台,商品表`products(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), description TEXT, category VARCHAR(50))`,每天有大量的商品数据新增和更新,同时用户会频繁地通过商品名称和描述进行全文检索。要求设计一个MySQL全文检索架构,既要保证数据的一致性和高可用性,又要兼顾检索性能,详细阐述你的设计思路、涉及的技术点以及如何应对数据量增长和高并发访问。
46.5万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 数据存储:使用MySQL的InnoDB存储引擎,因为它支持事务,能保证数据一致性,且在高并发场景下性能较好。
  2. 全文索引:对商品名称和描述字段添加全文索引。MySQL 5.6及以上版本支持对InnoDB表的全文索引。这样在进行全文检索时,能大大提高查询性能。
  3. 读写分离:为保证高可用性和应对高并发读操作,采用主从复制架构。主库负责处理写操作(商品数据新增和更新),从库负责处理读操作(全文检索)。这样可以分散负载,提高整体性能。
  4. 缓存机制:在从库前添加缓存,如Redis。对于频繁查询的结果可以先从缓存中获取,减少数据库的压力,进一步提高检索性能。

涉及技术点

  1. MySQL全文索引:通过ALTER TABLE products ADD FULLTEXT(name, description);语句来创建全文索引。在查询时使用MATCH AGAINST语法,例如SELECT * FROM products WHERE MATCH(name, description) AGAINST('查询关键词' IN NATURAL LANGUAGE MODE);
  2. 主从复制:在主库配置文件(my.cnf)中设置log-bin开启二进制日志,在从库配置server-id并通过CHANGE MASTER TO语句连接主库,启动从库复制线程。主库的写操作记录在二进制日志中,从库通过I/O线程读取并应用到自身,实现数据同步。
  3. Redis缓存:使用Redis的SET和GET命令来存储和获取缓存数据。在查询时先尝试从Redis获取数据,如果不存在则查询数据库,并将结果存入Redis。例如在PHP中使用如下代码:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cacheKey = md5('查询关键词');
$result = $redis->get($cacheKey);
if (!$result) {
    // 查询数据库
    $sql = "SELECT * FROM products WHERE MATCH(name, description) AGAINST('查询关键词' IN NATURAL LANGUAGE MODE)";
    // 执行SQL并获取结果
    $result = $db->query($sql)->fetchAll();
    $redis->set($cacheKey, serialize($result));
} else {
    $result = unserialize($result);
}

应对数据量增长和高并发访问

  1. 数据量增长
    • 水平分区:当数据量过大时,可以对商品表按某个字段(如时间、商品类别等)进行水平分区。例如按商品类别分区,不同类别的商品存储在不同的分区中,查询时只在相关分区中进行,减少扫描的数据量。
    • 分库分表:如果单个数据库服务器无法承载,可采用分库分表策略。将商品数据按一定规则(如哈希取模)分布到多个数据库和表中,从而降低单个库表的压力。
  2. 高并发访问
    • 增加从库数量:根据读操作的并发量,适当增加从库数量,将读请求进一步分散,提高整体读性能。
    • 优化SQL:对查询语句进行性能优化,如合理使用索引、避免全表扫描等。同时定期分析和优化数据库的查询执行计划。
    • 负载均衡:在主从库集群前添加负载均衡器,如Nginx或HAProxy。它可以将请求均匀分配到各个数据库服务器上,避免单个服务器压力过大。