在测试账户系统过程中遇到了线上大面积用户登录态失效的严重问题,事后对于其原因及测试盲点做了一些总结记录以便以后查阅,总结分为以下7点,其中原理性的解释有些摘自网络。

1.账户系统token失效问题复盘
2.Redis 经典流程
3.Redis分片部署方式
4.Redis扩容导致缓存数据失效
5.Redis Sharding一致性hash算法
6.缓存失效,缓存击穿,缓存穿透
7.Redis缓存测试总结

账户系统token失效问题复盘
现象:redis扩容后线上大量用户登录态失效,需要重新登录。由于登录态可以持续保持,部分用户忘记密码,需要修改密码后再次登录。在测试验证中,由于切换环境、登录登出导致这个问题难以发现和注意。

原因:sharded-redis-pool分片规则中有域名因子(框架源码中),扩容修改了redis域名,导致redis中数据虽然存在,概率性获取不到。
PS:失效问题复盘中有较多关于BUG修复前后代码差异的片段由于保密未贴出,一般来说测试复盘过程中对于代码的解析是很重要的一环。

Redis经典流程

前端测试盲点:
1.有些应用临时数据都存储在redis里,不存储在DB里
2.上面流程中redis的数据不管有没有生效,程序都可以正常进行,且功能正常
3.redis如果是集群的方式,缓存数据的读取和写入有没有进入正确的分片

Redis分片部署方式
(1)在客户端(jedis)做分片(Redis Sharding);这种方式在客户端确定要连接的redis实例,然后直接访问相应的redis实例(目前系统使用的方式)。
(2)在代理中做分片;这种方式中,客户端并不直接访问redis实例,它也不知道自己要访问的具体是哪个redis实例,而是由代理转发请求和结果;其工作过程为:客户端先将请求发送给代理,代理通过分片算法确定要访问的是哪个redis实例,然后将请求发送给相应的redis实例,redis实例将结果返回给代理,代理最后将结果返回给客户端。
(3)在redis服务器端做分片(Redis Cluster);这种方式被称为“查询路由”,在这种方式中客户端随机选择一个redis实例发送请求,如果所请求的内容不再当前redis实例中它会负责将请求转交给正确的redis实例,也有的实现中,redis实例不会转发请求,而是将正确redis的信息发给客户端,由客户端再去向正确的redis实例发送请求。

Redis扩容导致缓存数据失效
假设有三台缓存服务器,缓存tokenkey,希望tokenkey被均匀的缓存到这三台服务器上,原始的做法是对缓存项的键进行哈希,将哈希后的结果对缓存服务器的数量进行取模操作。

假设三台缓存服务器已经不能满足业务缓存需求,需要增加机器,就会出现一些缺陷。假设增加一台服务器,缓存服务器的数量由三台变为四台,此时,如果仍用取模的方法对同一tokenkey进行缓存,那么这个tokenkey所在的服务器编号就肯定与原来三台服务器时所在的编号不同。这就导致了缓存在一定时间内是失效的,当应用无法从缓存中获取数据,则会向后端服务请求数据,由于大量缓存同一时间失效,造成缓存的雪崩,可能导致系统被压垮。

Redis Sharding一致性hash算法
一致性hash:一致性哈希算法也是使用取模的方法,只是一致性哈希算法是对232取模。
我们有ABC三台服务器,使用各自的IP地址进行哈希计算,使用哈希后的结果对232取模,计算结果映射到一个由232个点组成的哈希圆环上,可以得到如下的示意图:

假设有4个tokenkey,1234需要缓存,根据hash(tokenkey)% 232得到的映射图如下,tokenkey1、2存储到A中,tokenkey3存储到B中,tokenkey4存储到C中。

假设机器B出现故障,需要移除服务器B,那么移除后的示意图如下。

当服务器移除以后,按照之前的一致性哈希算法的规则,tokenkey3应该被缓存到服务器C中,tokenkey3的缓存位置发生了改变。但是tokenkey1、2仍被缓存到服务器A中,tokenkey4仍被缓存到服务器C中,这就是一致性哈希算法的优点,当服务器数量发生改变,并不是缓存都会失效,而是只有部分缓存会失效,前端的缓存仍能分担整个系统的压力,不至于所有压力在同一时间集中到后端服务器上。

Hash环的偏斜及虚拟结点:

在实际的映射中,服务器可能会被映射成如下图:

虚拟节点是实际节点在hash环上的复制品,一个实际节点可以对应多个虚拟节点。虚拟节点可以解决hash环的偏斜以及缓存雪崩的问题。

缓存失效、缓存击穿、缓存穿透
缓存穿透
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
解决方案
有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

缓存雪崩
缓存雪崩是指在我们设置缓存时采用了相同的过期时间或者其他情况,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
解决方案
缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

缓存击穿
对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方案
使用互斥锁(mutex key)
简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

Redis集群缓存测试总结
功能:
1.系统运行过程中,redis缓存数据生效。缓存的数据读取正确、数据写入落地正确,数据有效期设置合理。
2.redis集群分片策略验证正确。
3.缓存与数据库的数据一致性检测。
4.DB事务性导致回滚,缓存是否回滚,有没有产生脏数据。
5.注意测试环境与线上环境的区别,尤其是单例与集群分片、读写分离。尽量保持测试环境与线上一致或者是其缩小版。

自动化:
1.自动化用例中断言部分设计缓存层断言并且自动化框架本身对于断层层次可配置。

性能及稳定性:
1.关注业务本身应用场景及缓存结构,是否使用缓存。
2.预防缓存穿透、缓存雪崩、缓存击穿引发的系统风险。

扩容:
1.关注扩容方案设计、老数据备份策略、回滚方案
2.关注扩容后分片策略的变化
3.扩容后热点数据失效率或命中率以及对后端DB带来的压力

Redis 集群缓存测试要点--关于 线上 token 失效 BUG 的总结的更多相关文章

  1. C#使用Redis集群缓存

    C#使用Redis集群缓存 本文介绍系统缓存组件,采用NOSQL之Redis作为系统缓存层. 一.背景 系统考虑到高并发的使用场景.对于并发提交场景,通过上一章节介绍的RabbitMQ组件解决.对于系 ...

  2. <正则吃饺子> :关于redis集群的测试demo

    redis集群的测试demo,来自网络,具体不详. 1.下载地址,如下:http://download.csdn.net/detail/u012543819/9729291 2.项目是java项目,结 ...

  3. Net分布式系统之五:C#使用Redis集群缓存

    本文介绍系统缓存组件,采用NOSQL之Redis作为系统缓存层. 一.背景 系统考虑到高并发的使用场景.对于并发提交场景,通过上一章节介绍的RabbitMQ组件解决.对于系统高并发查询,为了提供性能减 ...

  4. redis集群的测试

    原文:http://blog.sina.com.cn/s/blog_53b45c4d0102wg10.html 1.测试存取值 客户端连接集群redis-cli需要带上 -c ,redis-cli - ...

  5. 带你自行搭建虚拟机和Redis集群环境,值得收藏!

    前言: 我们看到分析 Redis 使用或原理的文章不少,但是完整搭建一套独立的 redis 集群环境的介绍,并不是很多或者说还不够详细. 那么,本文会手把手带着大家搭建一套 Redis 集群环境,Re ...

  6. Docker镜像配置redis集群

    redis版本:3.2.3 架构: 3节点redis集群,并为每个节点设置一个备用节点,共6个节点 1.安装redis镜像 docker load < docker.redis.tar.gz 2 ...

  7. redis集群与分片(2)-Redis Cluster集群的搭建与实践

    Redis Cluster集群 一.redis-cluster设计 Redis集群搭建的方式有多种,例如使用zookeeper等,但从redis 3.0之后版本支持redis-cluster集群,Re ...

  8. phpredis Redis集群 Redis Cluster

    官方url: https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#readme 2017年10月29日20:44:25 ...

  9. (转)高性能网站架构之缓存篇—Redis集群搭建

    看过 高性能网站架构之缓存篇--Redis安装配置和高性能网站架构之缓存篇--Redis使用配置端口转发 这两篇文章的,相信你已经对redis有一定的了解,并能够安装上,进行简单的使用了,但是在咱们的 ...

随机推荐

  1. Chapter 6. Names

    6.2. Names and Identifiers A name is used to refer to an entity declared in a program. There are two ...

  2. 【开源组件】FastDFS极速入门与安装

    FastDFS是一个开源的轻量级的分布式文件系统,为互联网量身定制,充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供 ...

  3. Weblogic Maven

    从weblogic 10.3.4开始支持maven deploy部署   步骤如下: 1.构建weblogic-maven-plugin jar 在D:\oracle\Middleware\wlser ...

  4. Python基础 - 总则

    学习Python的笔记,有基础语法,有注意点.仅此而已. 目录: ------------------------------------------- Python基础(1) - 初识Python ...

  5. 证书透明度Certificate Transparency

    发现使用google浏览器访问HTTPS网址时,点击小锁-->>连接-->>有一项服务器未提供任何 certificate transparency 信息?只有google浏览 ...

  6. 每天一道leetcode234-回文链表

    考试结束,班级平均分只拿到了年级第二,班主任于是问道:大家都知道世界第一高峰珠穆朗玛峰,有人知道世界第二高峰是什么吗?正当班主任要继续发话,只听到角落默默想起来一个声音:”乔戈里峰” 前言 2018. ...

  7. angular2自学笔记(二)---路由、服务等八大主要构造块

    angular的思想:总是把数据访问工作委托给一个支持性服务类. Angular 应用的:用 Angular 扩展语法编写 HTML 模板, 用组件类管理这些模板,用服务添加应用逻辑, 用模块打包发布 ...

  8. IOS折线图二

    上周把项目的折线图给做了下,今天想着把它完善完善,自己设置了不同的数据源来测试,哈哈,还真遇到问题了, 就是给图表设置折点数为0时,视图显示的还是原来的,由于数据为空,应该将其设置为空,所以想着怎么把 ...

  9. [转]Calling an OData Service From a .NET Client (C#)

    本文转自:https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata- ...

  10. 信号量 P V测试详解

    信号量 当我们编写的程序使用了线程时,不管它是运行在多用户系统上,多进程系统上,还是运行在多用户多进程系统上,我们通常会发现,程序中存在着一部分临界代码,我们需要确保只有一个进程可以进入这个临界代码并 ...