Spring Data默认值的错误

Posted JavaEdge.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Data默认值的错误相关的知识,希望对你有一定的参考价值。

Spring Data有很多配置的默认值,但不一定都适合你。如一个依赖Cassandra 的项目,有时写入数据后,并不能立马读到。这种错误并没有什么报错,一切都是正常的,就是读不到数据。

1 源码解析

直接使用 Spring Data Cassandra 操作时,实际依赖 Cassandra driver 内部的配置文件,目录:

.m2\\repository\\com\\datastax\\oss\\java-driver-core\\4.6.1\\java-driver-core-4.6.1.jar!\\reference.conf

很多默认配置,很重要配置是 Consistency,driver中默认为 LOCAL_ONE:

basic.request 
 

  # The consistency level.
  #
  # Required: yes
  # Modifiable at runtime: yes, the new value will be used for requests issued after the change.
  # Overridable in a profile: yes
  consistency = LOCAL_ONE
 
//省略其他非关键配置 

执行读写操作时,都会使用 LOCAL_ONE。运行时配置调试截图:

Cassandra 使用核心原则:使R(读)+W(写)>N,即读和写的节点数之和大于备份数。

设数据备份 3 份,待写入数据分别存储在 A、B、C 节点。常见搭配是 R(读)和 W(写)的一致性都是 LOCAL_QURAM,这样可以保证能及时读到写入的数据;而假设在这种情况下,读写都用 LOCAL_ONE,则可能发生这样的情况:用户写入一个节点 A 就返回,但用户 B 立马读的节点是 C,由于是LOCAL_ONE 一致性,则读完 C 就可立马返回。此时,就会出现数据读取可能落空case。

为何Cassandra driver 默认使用 LOCAL_ONE?其实是最合适的,因为只有一台机器,读写都只能命中一台。但产线上的 Cassandra 大多都是多数据中心多节点的,备份数大于1。所以读写都用 LOCAL_ONE 就会出现问题。

修正

修改默认值,以 consistency 为例。

@Override
protected SessionBuilderConfigurer getSessionBuilderConfigurer() 
    return cqlSessionBuilder -> 
        DefaultProgrammaticDriverConfigLoaderBuilder defaultProgrammaticDriverConfigLoaderBuilder = new DefaultProgrammaticDriverConfigLoaderBuilder();
        driverConfigLoaderBuilderCustomizer().customize(defaultProgrammaticDriverConfigLoaderBuilder);
        cqlSessionBuilder.withConfigLoader(defaultProgrammaticDriverConfigLoaderBuilder.build());
        return cqlSessionBuilder;
    ;


@Bean
public DriverConfigLoaderBuilderCustomizer driverConfigLoaderBuilderCustomizer() 
    return loaderBuilder -> loaderBuilder
            .withString(REQUEST_CONSISTENCY, ConsistencyLevel.LOCAL_QUORUM.name())

将一致性级别从 LOCAL_ONE 改成了 LOCAL_QUARM,符合实际产品部署和应用情况。

以上是关于Spring Data默认值的错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用spring-data-solr编写查询,返回特定字段的所有值的列表

使用Spring-Data-JPA进行Spring启动:每次请求时都会填充ArrayList / JSON对象

spring mvc上传文件表单同时传值的问题

如何在 Spring @Value 注解中正确指定默认值?

C# 4.0:我可以使用 TimeSpan 作为具有默认值的可选参数吗?

大家有没有遇到使用spring data jpa hibernate无法自动写入时间戳的问题?