注:不管采用主从的方式扩展读性能,还是缓存的方式扩展读性能,数据都要复制多份(主+从,db+cache),一定会引发一致性问题。
主从数据库的一致性,通常有两种解决方案
1)中间件
如果某一个key有写操作,在不一致时间窗口内,中间件会将这个key的读操作也路由到主库上。
这个方案的缺点是,数据库中间件的门槛较高(百度,腾讯,阿里,360等一些公司有)。
2)强制读主
实际用的“双主当主从用”的架构,不存在主从不一致的问题。
第二类不一致,是db与缓存间的不一致
1)常见缓存架构写顺序
淘汰cache == > 写数据库;
2)读操作的顺序
读cache,如果cache hit则返回;
如果cache miss,则读从库;
读从库后,将数据放回cache;
问题:从库读到旧数据(同步还没有完成),旧数据入cache
在经验“主从同步延时窗口时间”后,再次发起一个异步淘汰cache的请求;带来的代价是,多引入一次读miss(成本可以忽略)。
除此之外,最佳实践之一是:建议为所有cache中的item设置一个超时时间。
1.6 解决大并发问题 绍1、请求接口的合理设计
1. 一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。
2. 通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。
3. 这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。
4. 为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。
2、重启与过载保护
1. 秒杀和抢购的场景,流量往往是超乎我们系统的准备和想象的。
2. 如果检测到系统满负载状态,拒绝请求也是一种保护措施。
1.7 作弊的手段:进攻与防守1、同一个账号,一次性发出多个请求
1)问题描述
1. 例如一个简单的领取逻辑,先判断用户是否有参与记录,如果没有则领取成功,最后写入到参与记录中。
2. 然而,在某个请求成功写入参与记录的时间差内,其他的请求获查询到的结果都是“没有参与记录”。
2)应对方案
1. 在程序入口处,一个账号只允许接受1个请求,其他请求过滤,不仅解决了同一个账号,发送N个请求的问题,还保证了后续的逻辑流程的安全。
2. 实现方案,可以通过Redis这种内存缓存服务,写入一个标志位(只允许1个请求写成功,结合watch的乐观锁的特性),成功写入的则可以继续参加。
2、 多个账号,一次性发送多个请求
1)问题描述