文章插图
常见的缓存架构如上,此时写操作的顺序是:
(1)淘汰cache;
(2)写数据库;
读操作的顺序是:
(1)读cache,如果cache hit则返回;
(2)如果cache miss,则读从库;
(3)读从库后,将数据放回cache;
在一些异常时序情况下,有可能从【从库读到旧数据(同步还没有完成),旧数据入cache后】,数据会长期不一致 。解决办法是“缓存双淘汰”,写操作时序升级为:
(1)淘汰cache;
(2)写数据库;
(3)在经验“主从同步延时窗口时间”后,再次发起一个异步淘汰cache的请求;
这样,即使有脏数据如cache,一个小的时间窗口之后,脏数据还是会被淘汰 。带来的代价是,多引入一次读miss(成本可以忽略) 。
除此之外,最佳实践之一是:建议为所有cache中的item设置一个超时时间 。
- 6. 如何提高数据库的扩展性?
如何秒级扩容?
首先,我们不做2库变3库的扩容,我们做2库变4库(库加倍)的扩容(未来4->8->16)
文章插图
服务+数据库是一套(省去了缓存),数据库采用“双主”的模式 。
扩容步骤:
第一步,将一个主库提升;
第二步,修改配置,2库变4库(原来MOD2,现在配置修改后MOD4),扩容完成;
原MOD2为偶的部分,现在会MOD4余0或者2;原MOD2为奇的部分,现在会MOD4余1或者3;数据不需要迁移,同时,双主互相同步,一遍是余0,一边余2,两边数据同步也不会冲突,秒级完成扩容!
最后,要做一些收尾工作:
- 将旧的双主同步解除;
- 增加新的双主(双主是保证可用性的,shadow-master平时不提供服务);
- 删除多余的数据(余0的主,可以将余2的数据删除掉);
文章插图
这样,秒级别内,我们就完成了2库变4库的扩展 。
#5 大并发带来的挑战# ##5.1 请求接口的合理设计## 一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口 。
通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上 。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果 。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点 。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入 。
文章插图
当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功 。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作” 。
##5.2 高并发的挑战:一定要“快”## 我们通常衡量一个Web系统的吞吐率的指标是QPS(Query Per Second,每秒处理请求数),解决每秒数万次的高并发场景,这个指标非常关键 。举个例子,我们假设处理一个业务请求平均响应时间为100ms,同时,系统内有20台Apache的Web服务器,配置MaxClients为500个(表示Apache的最大连接数目) 。
那么,我们的Web系统的理论峰值QPS为(理想化的计算方式):
咦?我们的系统似乎很强大,1秒钟可以处理完10万的请求,5w/s的秒杀似乎是“纸老虎”哈 。实际情况,当然没有这么理想 。在高并发的实际场景下,机器都处于高负载的状态,在这个时候平均响应时间会被大大增加 。
就Web服务器而言,Apache打开了越多的连接进程,CPU需要处理的上下文切换也越多,额外增加了CPU的消耗,然后就直接导致平均响应时间增加 。因此上述的MaxClient数目,要根据CPU、内存等硬件因素综合考虑,绝对不是越多越好 。可以通过Apache自带的abench来测试一下,取一个合适的值 。然后,我们选择内存操作级别的存储的Redis,在高并发的状态下,存储的响应时间至关重要 。网络带宽虽然也是一个因素,不过,这种请求数据包一般比较小,一般很少成为请求的瓶颈 。负载均衡成为系统瓶颈的情况比较少,在这里不做讨论哈 。
推荐阅读
- 基于redis分布式锁实现“秒杀”
- 小米刷机后使用不习惯,想要恢复原系统?可以采用这种方式来恢复
- iOS 屏蔽系统更新描述文件更新!快把烦人的系统更新提示关掉
- MySQL 整体架构与 SQL 执行原理
- 分布式系统常见概念
- PHP的微服务框架预览
- 详解Rsync远程同步服务在windows系统下的安装和配置
- 电商支付架构设计
- 详解Docker架构原理、功能及使用
- 升级鸿蒙后内存突然满了 鸿蒙系统占用手机多少g