GaussDB(for Redis)企业级特性揭秘之多租户管理

【摘要】 华为云GaussDB(for Redis)持续完善企业级增强特性,是名副其实的"Redis Plus",其中很经典的企业级特性是多租户能力,支持添加只读账号、读写账号,并且可约束每个账号可访问的数据库(DB)范围,避免误操作其他租户数据。该特性可以帮助企业在共享Redis实例的情况下,保护不同租户的数据安全,为企业的开发和管理提供便利。哪些用户需要使用租户管理功能?多租户是数据库用户刚需的一...

华为云GaussDB(for Redis)持续完善企业级增强特性,是名副其实的"Redis Plus",其中很经典的企业级特性是多租户能力,支持添加只读账号、读写账号,并且可约束每个账号可访问的数据库(DB)范围,避免误操作其他租户数据。该特性可以帮助企业在共享Redis实例的情况下,保护不同租户的数据安全,为企业的开发和管理提供便利。

哪些用户需要使用租户管理功能?

多租户是数据库用户刚需的一个功能,例如,企业中有两个业务部门A和B,他们都需要使用Redis来存储自己的数据,如果不使用多租户权限功能,那么A和B的数据就会混在一起,这样就会存在数据泄露和误操作的风险。一旦使用了多租户管理功能,就可以将A和B的数据分别存储在不同的Redis实例/DB中,并且对这些实例/DB进行权限控制,从而保障数据的安全性和可靠性。

在数据库领域,多租户技术往往有以下一些标准属性:比如读写权限控制、跨DB鉴权隔离等等;而GaussDB(for Redis)就是具备完善的多租户管理技术的一个典范,实现了读写权限控制和数据库(DB)隔离这两大特性的完美融合。

Redis 6.0已具备ACL功能,为什么还要使用GaussDB(for Redis)的多租户功能?
关于权限控制,开源Redis虽然在6.0新版本有ACL,但只能设置为只读、读写,每个账号还是可以看到所有的DB的。这个设计比较鸡肋,跟数据库多租户的原理背道而驰。举个例子,业务开发小王应该用DB1,但有天忘记SELECT,不小心清库了小张的DB0,导致生产事故。而GaussDB(for Redis)的权限隔离就从根源上解决了这个问题,如小王被设置为只有DB1的权限而没有DB0的权限,那么即使他误操作也不会对DB0的数据产生影响。

此外,开源Redis的多租户功能只有单机才可以使用,一旦业务上量需要集群,多DB功能反而就不可用了,只剩一个DB0;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了实现Redis的多租户,我们可以使用Redis的多数据库特性,为每个租户分配一个独立的数据库。同时,我们还需要使用Spring Boot的多数据源配置来实现多Redis数据源的配置。以下是实现Redis租户的步骤: 1.在Redis中为每个租户分配一个独立的数据库,可以使用SELECT命令来切换数据库。例如,使用SELECT 0选择第一个数据库,使用SELECT 1选择第二个数据库,以此类推。 2.在Spring Boot中配置多Redis数据源,可以使用MultiRedisTemplate来实现。MultiRedisTemplate是一个自定义的RedisTemplate,它可以管理多个Redis数据源。我们需要在配置文件中为每个Redis数据源配置不同的属性,例如host、port、password等。 3.在Redis数据源上下文切换RedisConfig中,我们需要使用ThreadLocal来存储当前租户的数据库编号。在每次访问Redis时,我们需要根据当前租户的数据库编号来切换到对应的数据库。 以下是一个简单的示例代码,演示如何实现Redis租户: ```java // Redis租户配置类 @Configuration public class MultiRedisConfig { @Bean(name = "redis1") @ConfigurationProperties(prefix = "spring.redis1") public JedisConnectionFactory redis1ConnectionFactory() { return new JedisConnectionFactory(); } @Bean(name = "redis2") @ConfigurationProperties(prefix = "spring.redis2") public JedisConnectionFactory redis2ConnectionFactory() { return new JedisConnectionFactory(); } @Bean(name = "multiRedisTemplate") public MultiRedisTemplate multiRedisTemplate(@Qualifier("redis1") RedisConnectionFactory redis1ConnectionFactory, @Qualifier("redis2") RedisConnectionFactory redis2ConnectionFactory) { MultiRedisTemplate multiRedisTemplate = new MultiRedisTemplate(); Map<String, RedisConnectionFactory> connectionFactoryMap = new HashMap<>(); connectionFactoryMap.put("redis1", redis1ConnectionFactory); connectionFactoryMap.put("redis2", redis2ConnectionFactory); multiRedisTemplate.setTargetRedisTemplateMap(connectionFactoryMap); return multiRedisTemplate; } } // Redis数据源上下文切换类 public class RedisContextHolder { private static final ThreadLocal<Integer> contextHolder = new ThreadLocal<>(); public static void setDataSource(Integer dataSource) { contextHolder.set(dataSource); } public static Integer getDataSource() { return contextHolder.get(); } public static void clearDataSource() { contextHolder.remove(); } } // Redis租户模板类 public class MultiRedisTemplate extends RedisTemplate<String, Object> { private Map<String, RedisConnectionFactory> targetRedisTemplateMap; @Override public void afterPropertiesSet() { RedisConnectionFactory defaultTargetConnectionFactory = targetRedisTemplateMap.get("redis1"); setConnectionFactory(defaultTargetConnectionFactory); super.afterPropertiesSet(); } @Override protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) { Integer dataSource = RedisContextHolder.getDataSource(); if (dataSource != null) { RedisConnectionFactory targetConnectionFactory = targetRedisTemplateMap.get("redis" + dataSource); connection = targetConnectionFactory.getConnection(); } return super.preProcessConnection(connection, existingConnection); } public void setTargetRedisTemplateMap(Map<String, RedisConnectionFactory> targetRedisTemplateMap) { this.targetRedisTemplateMap = targetRedisTemplateMap; } } // 在业务代码中使用Redis租户模板类 @Service public class RedisService { @Autowired private MultiRedisTemplate multiRedisTemplate; public void setValue(String key, Object value) { RedisContextHolder.setDataSource(1); // 切换到第二个数据库 multiRedisTemplate.opsForValue().set(key, value); RedisContextHolder.clearDataSource(); // 切换回默认数据库 } public Object getValue(String key) { RedisContextHolder.setDataSource(2); // 切换到第三个数据库 Object value = multiRedisTemplate.opsForValue().get(key); RedisContextHolder.clearDataSource(); // 切换回默认数据库 return value; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值