Redis如何合理缓存部门信息

CREATE TABLE `t_department` (
  `id` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键ID',
  `parent_id` char(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上级部门ID',
  `name` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '部门名称',
  `en_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '部门英文名称',
  `short_name` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '部门简称',
  `level` tinyint DEFAULT NULL COMMENT '部门级别',
  `sort_order` tinyint DEFAULT NULL COMMENT '排序',
  `remark` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
  `has_delete` bit(1) DEFAULT b'0' COMMENT '是否删除: {[1:删除:true] [0:未删除:false]}',
  `update_time` datetime(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
  `create_time` datetime(3) DEFAULT (3) COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='部门表';
 
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('61A4A415109F512D26BF076D328A57D2', NULL, 'XXX科技有限公司', NULL, NULL, 0, 1, NULL, b'0', '2022-05-17 22:45:47.845', '2022-05-17 22:42:54.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('DEF4C715F5F3A6638710831150750931', '61A4A415109F512D26BF076D328A57D2', '总裁办', NULL, NULL, 1, 1, NULL, b'0', '2022-05-17 22:46:35.366', '2022-05-17 22:46:15.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('F7196AD72378A40227B08EFA03A37342', '61A4A415109F512D26BF076D328A57D2', '研发中心', NULL, NULL, 1, 2, NULL, b'0', '2022-05-17 23:11:02.413', '2022-05-17 22:51:07.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('9BE108797F0729D7B3255378A42BC65B', '61A4A415109F512D26BF076D328A57D2', '国内营销中心', NULL, NULL, 1, 3, NULL, b'0', '2022-05-17 22:56:50.634', '2022-05-17 22:56:25.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('512FB3B019246A8024C0CEFC38201A35', '61A4A415109F512D26BF076D328A57D2', '国际营销中心', NULL, NULL, 1, 4, NULL, b'0', '2022-05-17 22:57:43.678', '2022-05-17 22:57:24.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('57C27BF286904D54CE9932F5730A0386', '61A4A415109F512D26BF076D328A57D2', '国际运营中心', NULL, NULL, 1, 5, NULL, b'0', '2022-05-17 22:58:45.528', '2022-05-17 22:58:14.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('164BC8A06A17735347A939E6D45EF833', '61A4A415109F512D26BF076D328A57D2', '行政人事中心', NULL, NULL, 1, 6, NULL, b'0', '2022-05-17 22:59:29.048', '2022-05-17 22:58:50.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('DC4A6BA92928CD12DB488C15DB57192E', 'F7196AD72378A40227B08EFA03A37342', '终端部', NULL, NULL, 2, 1, NULL, b'0', '2022-05-17 23:01:32.645', '2022-05-17 23:01:04.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('8D0F03C1CA8988106419A539BC978223', 'F7196AD72378A40227B08EFA03A37342', '系统部', NULL, NULL, 2, 2, NULL, b'0', '2022-05-17 23:02:18.483', '2022-05-17 23:02:02.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('53B53DDBBAA370C187AF21531E01F51F', 'F7196AD72378A40227B08EFA03A37342', '硬件部', NULL, NULL, 2, 3, NULL, b'0', '2022-05-17 23:03:11.796', '2022-05-17 23:02:47.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('833DEE5B80F2FEDD302A5DE2DC090850', 'F7196AD72378A40227B08EFA03A37342', '固件部', NULL, NULL, 2, 4, NULL, b'0', '2022-05-17 23:03:49.636', '2022-05-17 23:03:45.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('5574768EC08C12E82C34CEBE08734ABD', '8D0F03C1CA8988106419A539BC978223', '开发一部', NULL, NULL, 3, 1, NULL, b'0', '2022-05-17 23:05:16.745', '2022-05-17 23:05:02.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('367C70A77568E2BD0094D0EB31DA3721', '8D0F03C1CA8988106419A539BC978223', '开发一部', NULL, NULL, 3, 2, NULL, b'0', '2022-05-17 23:05:58.480', '2022-05-17 23:05:46.000');
INSERT INTO `t_department` (`id`, `parent_id`, `name`, `en_name`, `short_name`, `level`, `sort_order`, `remark`, `has_delete`, `update_time`, `create_time`) VALUES ('E6725F4A77FC56D49F046F7F7A7133A5', '8D0F03C1CA8988106419A539BC978223', '开发三部', NULL, NULL, 3, 3, NULL, b'0', '2022-05-17 23:06:35.088', '2022-05-17 23:06:03.000');

需求

  • 点击进入部门页面,查出所有一级部门列表,点击某个部门返回它的下一级部门列表,以此类推
  • 部门列表展示的时候还需要展示这个部门的人数字段
  • 还需要提供一个接口查处整个部门树
    目前做法
    用Redis的hash结构缓存所有部门信息key为部门ID value为部门信息,每查下一级部门都需要把整个缓存查出来代码中做过滤,过来出来的部门在循环查出每个部门有多少人。想请问有没有好的缓存结构或方式
阅读 2.5k
2 个回答

首先缓存是典型的空间换时间的做法,所以不要吝啬任何空间,能换来性能的提升不要怕数据冗余

在管理部门的时候把所有可能用到的一维数据,全部生成一遍缓存,需要的时候,根据key的规范直接取,原则就是根据约定的key就可以获取想要的数据,不需要额外处理,比如:

所需数据缓存
整个部门树t_department_tree
一级部门t_department_top
根据上级部门ID缓存所有下级部门数据t_department_top_{pid}

以此类推,前期尽量考虑全,不够再去补也不是什么大问题

已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。

三种方案,各有优缺点,推荐后两种:

方案一:
可以将 redis 的 key 设置为 parent_id + id 的形式
顶级部门 parent_id 为字符串 "null"
作为一个hash存到一个key下
比如:

null_1
null_2
1_3
1_4
2_5

这样在使用的时候
可以通过
HSCAN key 0 null_* count x 查询所有顶级部门
HSCAN key 0 1_* count x 查询所有部门1下的部门
优点:数据不冗余
缺点:性能比较低

方案二:
每个部门存两个key,一个存这个部门的信息,一个存子部门的信息
比如:

String_1 : 部门1信息
Hash_1 : { 2 : 部门2信息, 3 : 部门3信息 }
String_2 : 部门2信息
String_3 : 部门3信息

这样需要查单个部门信息就用String_部门id
需要查子部门信息就用Hash_部门id
优点:查询简单,查询效率最高
缺点:数据维护工作量上升

方案三:
每个部门存两个key,一个存这个部门的信息,一个存子部门的key
比如:

String_1 : 部门1信息
Set_1 : [ 2, 3 ]
String_2 : 部门2信息
String_3 : 部门3信息

这样需要查单个部门信息就用String_部门id
需要查子部门信息就用Hash_部门id,查出子部门的id,再通过mget之类的所有的子部门信息
优点:数据不冗余,查询效率较高
缺点:需要多次查询,性能稍低

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏