舒服,又偷学到一个高并发场景面试题的解决方案。

本文讨论了在高并发环境下,如何有效统计页面浏览量(PV)。通过引入二级缓存,结合JVM内存和Redis,降低对Redis的访问压力。文章详细介绍了二级缓存的实现,包括时间块的概念,以及定时任务同步数据到数据库和Redis的过程,以实现高效并发处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高并发 PV 问题

他的文章标题是这样的:

图片

首先他给出了一个业务场景:在一些需要统计 PV(Page View), 即页面浏览量或点击量高并发系统中,如:知乎文章浏览量,淘宝商品页浏览量等,需要统计相应数据做分析。

比如我的公众号阅读量大概在 3000 左右,如果要统计我这种小号主的 PV 其实就很简单,就用 Redis 的 incr 命令轻轻松松就实现了。

但是,假设微信公众号每天要统计 10 万篇文章,每篇文章的访问量 10 万,如果采用 Redis 的 incr命令来实现计数器的话,每天 Redis=100 亿次的写操作,按照每天高峰 12 小时来算,那么 Redis 大约 QPS=57万。

如此大的并发量,CPU 肯定满负载运行,网络资源消耗也巨大,所以直接使用 incr 命令这种技术方案是行不通的。

图片

假设这是一个面试场景题,你会怎么去回答呢?

其实你也别想的有多复杂,剥离开场景,这无外乎就是一个高并发的问题。

而高并发问题的解决方案,基本上逃不过这三板斧:缓存、拆分、加钱。

所以这个老哥给出的方案就是:缓存。

二级缓存

Redis 都已经是缓存了,那么再加缓存算什么回事呢?

那就算是二级缓存了。

而且这个缓存,就在 JVM 内存里面,比 Redis 还快。

其核心思想是减少 Redis 的访问量。这些理论的东西,大家应该都知道。

那么通过什么方案去减少 Redis 的访问量呢,这个二级缓存应该怎么去设计呢?

首先,文章服务采用了集群部署,在线上可以部署多台。

然后每个文章服务,增加一级 JVM 缓存,即用 Map 存储在 JVM,key 为当前请求所属的时间块。

就是这个意思:

Map<Long,Map<Integer,Integer>> = Map<时间块,Map<文章id,访问量>>

但是我觉得巧妙的地方在于这里提到的“时间块”的概念。

什么是时间块?

就是把时间切割为一块块,例如:一篇文章在1小时,30分钟、5分钟的时间内产生了多少阅读量。

如何切割时间块呢?

这里利用到了时间是不断增长的特性。

时间戳是自 1970 年1月1日(00:00:00 GMT)至当前时间的总数,通过确定时间块大小,算出当前请求所属的时间戳从 1970 年算起位于第几个时间块,这个算出来的第几个时间块就是小时 key ,即 map 的 key。

举个例子:

我们把时间按照“小时”的维度进行划分。

先把当前的时间转换为为毫秒的时间戳,然后除以一小时,即当前时间 T/1000*60*60=小时key,然后用这个小时序号作为key。

比如:

2021-12-26 15:00:00 = 1640502000000毫秒

那么小时key= 1

### Mysql 场景面试题及详细解决方案 #### 面试题一:MySQL 查询优化 **问描述**: 如何通过索引来提升 MySQL 的查询性能? **解答**: 在 MySQL 中,可以通过合理创建索引来显著提升查询性能。对于频繁作为查询条件的字段,尤其是那些经常用于 `WHERE` 子句中的字段,应该优先考虑建立索引[^2]。需要注意的是,虽然索引能够加速查询操作,但它也会带来额外的维护成本,在更新数据时可能会减慢速度。 为了进一步优化查询性能,应尽量避免对字符串类型的字段进行索引,因为这些字段通常需要逐字节比较,而数字型字段仅需单次比较即可完成匹配[^3]。因此,在设计数据库结构时,建议将数值信息存储为数字类型而非字符类型。 --- #### 面试题二:SQL 执行流程分析 **问描述**: 一条 SQL 语句是如何被执行的? **解答**: 当客户端向 MySQL 发送一条 SQL 语句时,服务器端会依次经历以下几个阶段: 1. **解析器 (Parser)**: 将接收到的 SQL 文本转换成内部的数据结构表示形式。 2. **预处理器 (Preprocessor)**: 对语法树做初步验证并补充必要的上下文信息。 3. **优化器 (Optimizer)**: 负责决定最佳访问路径以最小化资源消耗。此过程可能涉及重写查询计划、选择合适的索引等策略。 4. **执行器 (Executor)**: 根据最终确定下来的执行方案实际运行命令并与存储引擎交互获取所需的结果集。 以上各环节紧密协作共同完成了从输入到输出整个生命周期内的所有必要工作[^1]。 --- #### 面试题三:高并发下的锁机制 **问描述**: 在高并发环境下如何解决因锁定而导致的性能瓶颈? **解答**: 针对不同业务需求可以选择适当级别的事务隔离级别来平衡一致性和吞吐量之间的矛盾;另外还可以采用乐观锁或者悲观锁的方式来控制共享资源的竞争状况。具体来说就是如果预计冲突概率较低则倾向于前者反之亦然。此外分区表技术也可以有效缓解热点区域的压力从而达到分流效果进而改善整体表现水平。 以下是实现行级加锁的一个简单例子: ```sql SELECT * FROM orders WHERE order_id = '100' FOR UPDATE; ``` 该语句会在指定记录上施加重叠范围更小粒度更高的排他性约束直到当前事务结束为止才能释放它所占用的权利给其他等待者尝试获得相同权限的机会。 --- #### 面试题四:大数据量分页查询优化 **问描述**: 当面对海量数据时,传统的 LIMIT 偏移方式会产生严重的性能问,请问有什么替代方法吗? **解答**: 可以改用主键自增列配合 IN 或 BETWEEN 来代替 OFFSET 实现逻辑上的翻页功能, 这样既可以避开全表扫描又能充分利用唯一标识符加快检索速度. 例如下面这个版本就比单纯依赖位置参数要高效得多: ```sql -- 获取第一页 SELECT id,name FROM users ORDER BY id ASC LIMIT 50; -- 下一页起始点设为前一批最后那个id值加上步长数量 SET @last_id :=( SELECT MAX(id) FROM users ); SELECT id,name FROM users WHERE id >@last_id AND ROWNUM<=50 ; ``` 这种方法不仅规避掉了重复计算前面部分所带来的负担同时也让后续请求更加精准迅速地直达目标区间范围内。 --- ### 总结 通过对上述几个典型场景下常见挑战的研究探讨可以看出掌握好基础理论知识结合实践经验积累是非常重要的。只有这样才能从容应对各种复杂情况做到游刃有余举重若轻的地步!
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值