当前位置: 首页 > 知识库问答 >
问题:

Cassandra:每个密钥空间的客户数据

濮阳君浩
2023-03-14

问题:我们的一个新客户希望数据存储在他自己的国家(法律法规)。然而,我们使用分布在不同国家的几个数据中心的现有客户数据。

问:我们如何在不太改变现有Cassandra架构的情况下,将新客户的数据分离到其自己的国家?

潜在的解决方案#1:为该客户使用单独的密钥空间。关键字空间之间的模式是相同的,这增加了数据迁移的复杂性,等等。DataStax支持确认可以为每个区域配置keyspace。然而,我们使用的Spring Data Cassandra不允许动态选择keyspace。唯一的方法是使用CqlTemplate并在每次调用之前运行use keyspace blabla,或者在表之前添加keyspaceselect*from blabla.mytable,但这听起来像是一个黑客。

共有1个答案

东方夕
2023-03-14

下面的示例和解释与GitHub中的相同

GitHub中的示例现在正在工作。未来最有效的解决方案似乎是使用存储库扩展。将很快更新下面的示例。

请注意,我最初发布的解决方案有一些缺陷,这些缺陷是我在JMeter测试中发现的。Datastax Java驱动html" target="_blank">程序参考建议避免通过session对象设置keyspace。您必须在每个查询中显式设置keyspace。

我将首先定义如何在每个请求上设置租户ID。一个很好的例子是使用特定的HTTP头来定义REST API:

Tenant-Id: ACME

类似地,在每个远程协议上,您可以在每个消息上转发租户ID。假设您使用的是AMQP或JMS,您可以在消息头或属性中转发这个消息。

接下来,您应该在控制器中存储每个请求的传入头。您可以使用ThreadLocal,也可以尝试使用请求范围的bean。

@Component
@Scope(scopeName = "request", proxyMode= ScopedProxyMode.TARGET_CLASS)
public class TenantId {

    private String tenantId;

    public void set(String id) {
        this.tenantId = id;
    }

    public String get() {
        return tenantId;
    }
}
@RestController
public class UserController {

    @Autowired
    private UserRepository userRepo;
    @Autowired
    private TenantId tenantId;

    @RequestMapping(value = "/userByName")
    public ResponseEntity<String> getUserByUsername(
            @RequestHeader("Tenant-ID") String tenantId,
            @RequestParam String username) {
        // Setting the tenant ID
        this.tenantId.set(tenantId);
        // Finding user
        User user = userRepo.findOne(username);
        return new ResponseEntity<>(user.getUsername(), HttpStatus.OK);
    }
}
public class KeyspaceAwareCassandraRepository<T, ID extends Serializable>
        extends SimpleCassandraRepository<T, ID>  {

    private final CassandraEntityInformation<T, ID> metadata;
    private final CassandraOperations operations;

    @Autowired
    private TenantId tenantId;

    public KeyspaceAwareCassandraRepository(
            CassandraEntityInformation<T, ID> metadata,
            CassandraOperations operations) {
        super(metadata, operations);
        this.metadata = metadata;
        this.operations = operations;
    }

    private void injectDependencies() {
        SpringBeanAutowiringSupport
                .processInjectionBasedOnServletContext(this,
                getServletContext());
    }

    private ServletContext getServletContext() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest().getServletContext();
    }

    @Override
    public T findOne(ID id) {
        injectDependencies();
        CqlIdentifier primaryKey = operations.getConverter()
                .getMappingContext()
                .getPersistentEntity(metadata.getJavaType())
                .getIdProperty().getColumnName();

        Select select = QueryBuilder.select().all()
                .from(tenantId.get(),
                        metadata.getTableName().toCql())
                .where(QueryBuilder.eq(primaryKey.toString(), id))
                .limit(1);

        return operations.selectOne(select, metadata.getJavaType());
    }

    // All other overrides should be similar
}
@SpringBootApplication
@EnableCassandraRepositories(repositoryBaseClass = KeyspaceAwareCassandraRepository.class)
public class DemoApplication {
...
}
    null
 类似资料:
  • 我已经用这个链接备份了我在卡桑德拉的密钥空间cassandra-backup.sh 为了恢复,我写了一个脚本,从包含快照的备份文件夹中复制内容,并粘贴到 /var/lib/cassandra/data/mykeypsace/下的相应目录中,但是当我看到mykeyspace的表内容时,没有恢复任何内容。例如,备份文件夹:path/mykeyspace/tableOne/snapshot/all-co

  • 我有一个nxt请求帖子与表单url编码使用Feign客户端

  • 问题内容: 我想知道是否有人尝试使用默认键空间构建cassandra docker镜像,但我尝试在BUILD时间内完成该操作,但由于cassandra不在该阶段运行,因此无法正常工作。这类似于以下内容: 我的新方法是从入口点脚本执行此操作,但是,如果其他人有更好的主意,我现在想。 快乐运输:D 问题答案: 今天解决了这个问题。构建映像,该映像将在修改之前附加一个修改过的默认Cassandra 将所

  • 我正在尝试将以下结构存储在卡桑德拉中。 上面的大多数查询是 这就是为什么将()设置为主键很有用的原因。 根据docu,Cassandra的默认分区键是主键的第一列-在我的例子中是,但我想在Cassandr集群上均匀分布数据,我不能允许一个中的所有数据只存储在一个分区中,因为有些商店有10M条记录,有些只有1k条记录。 我可以设置()作为分区键,然后我可以达到Cassandra集群中记录的统一分布。

  • 所以我有一张表,它看起来像这样: 我们依赖该表根据进行分页来正确排序。 问题是:当从cassandra返回结果时,看起来它们是根据ASCII值而不是逻辑的A-Z排序进行排序的。-对于观看它的人来说,这在程序上是有意义的,但在逻辑上是不合理的。 是否有一个选项来改变当前聚类顺序的方法? -或者另一种逻辑排序的方法?