用户信息缓存策略

由于前端需要用户信息userInfo,后端各个模块,例如报表也需要用户信息,查询的频率很高,涉及到较多的联表。

而实际系统用户较小,数据基本不变,为各模块方便查询,决定采取缓存。

选择将其放到Redis数据库中,访问用户数据时,模块间得到解耦。

1. 函数

userInfo的部分字段可能来自于函数。

由于需要,在我拿到一个用户的时候,我同时需要得知他是属于哪个顶级组织的。

组织表如下:

orgId orgName parentOrgId
1 老板 null
2 组织一 1
3 组织二 1

首先,创建一个函数,根据orgId获取rootId

CREATE FUNCTION `queryRoot`(org varchar(32))
 RETURNS varchar(32)
BEGIN

# 定义子节点、父节点
DECLARE nodeId VARCHAR(32);
DECLARE parentId VARCHAR(32);
DECLARE rootId VARCHAR(32);

# 赋值
SET nodeId = org;
SET parentId = '$';

WHILE parentId IS NOT NULL DO
	SELECT parentOrgId INTO parentId FROM T_ORG WHERE ORG_ID = nodeId;
	SET rootId = nodeId;
	SET nodeId = parentId;
END WHILE;

RETURN rootId;

END;

2. 视图

SELECT
	`users`.`USER_ID` AS `userId`,
	`users`.`ORG_ID` AS `orgId`,
	(
		SELECT
			`queryRootByOrgId` (`users`.`ORG_ID`)
	) AS `rootOrgId`,
	`orgs`.`ORG_NAME` AS `orgName`,
	`users`.`USER_NAME` AS `userName`
FROM
	(
		`T_USERS` `users`
		JOIN `T_ORG` `orgs` ON (
			(
				`users`.`ORG_ID` = `orgs`.`ORG_ID`
			)
		)
	)

3. 定时更新到Redis

其中用到了反射,将属性及值存到Hash里面。

@EnableScheduling
@Component
public class RedisTask {

    @Autowired
    private StringRedisTemplate redis;

    @Autowired
    private UserInfoRepository userInfoRepository;

    static Field[] fields;
    static {
        fields = UserInfo.class.getDeclaredFields();
        for (Field field : fields)
            field.setAccessible(true);
    }

    /**
     * 定时 3min 查询数据库,然后更新到 redis 中
     */
    @Scheduled(fixedRate = 3*60*1000)
    private void userInfo() {

        List<UserInfo> list = userInfoRepository.findAll();

        list.forEach(user -> {
            Map<String, String> map = new HashMap();
            String hashKey, hashValue, hash = user.getUserId();
            for (Field field : fields) {
                try {
                    hashKey = field.getName();
                    if (field.get(user) != null)
                        hashValue = field.get(user).toString();
                    else
                        hashValue = "";
                    map.put(hashKey, hashValue);
                } catch (Exception e) {
                    System.out.println("反射异常");
                    e.printStackTrace();
                }
            }
            redis.opsForHash().putAll(hash, map);
        });

    }

}

猜你喜欢

转载自my.oschina.net/u/3035165/blog/1649469