一、出现的线上问题
背景:
项目是给客户企业提供报表数据查询的saas平台,部门管理员只能查询当前部门下的数据
权限经常涉及到可以查看部门及子部门,如果下级部门较多或层级较多每次获取权限都去递归效率低且没必要。
大部分的权限设计都是在登陆或首次需要获取权限时调用获取权限的方法把权限相关的数据存到redis里面然后设置一个合理的过期时间(过期时长由实际业务决定)
出现的问题: 有时数据正常,有时所有页面没有数据,有时页面的数据不是当前用户权限下的数据
二、问题排查
key的组成:企业ID+登陆账号的员工ID
出现问题后,通过日志找到出问题的key:
- 根据key获取到的value有时候正常有时为空
- 根据key获取到的value不是当前用户的权限数据
发现以下两种情况:
-
与其他模块的缓存key冲突 举例:企业ID为1,员工ID为24的员工的缓存key是:124 其他模块缓存的key是某个表在mysql中的自增ID也有124
数据不正确的原因:获取数据的时候如果其他模块更新数据后新的数据缓存到redis中,当有用户登陆时拿到的就是其他模块的数据,解析时字段无法映射,拿到了空对象,取出所在的部门时,为null,页面没有任何数据 -
不同的企业ID+员工ID后组成的key冲突:
企业ID为1员工ID为24的员工的缓存key是:124
企业ID为12员工ID为4的员工缓存数据的key是:124
数据不正确的原因:获取数据的时候拿到的权限数据不一定是想要的员工对应权限
三、问题解决办法
- 在key前面加上业务相关的前缀比如:USER_AUTH
- 在不同的组成元素间加上_ 比如:企业ID+员工ID 改为{企业ID}_{员工ID} 举例:企业ID为1,员工ID为24的员工的缓存key是:USER_AUTH_1_24
四、总结
这种问题在设计redis key的时候就能避免,是非常简单的问题,测试和研发在工作中要有规范意识
规范参考:redis key 命名规范的设计