关于R2DBC和PostgreSQL的几句话

最近,我再次看到,关于反应式编程,尤其是对数据库的反应式工作,炒作已经普遍增加。我想说几句话。

图片

让我提醒您以前的系列中发生了什么。2017年底,Spring 5出现了,其中出现了对反应式编程的支持。特别是,我们在谈论WebFlux每个人都开始急剧尝试这项技术(典型的炒作曲线),然后业界意识到并非每个人都需要重新激活。获得的主要经验教训:

  • 反应性编程更难调试
  • 开发被动系统比经典的,封闭的系统要困难得多。如果您无意间阻塞了线程,则说明您已完成。这就是该项目出现的原因(其中一位作者-bsideup
  • 主要在Netflix的高负载下需要反应式编程,尤其是弹性。如果您有100 RPS,则可能应该以阻塞方式编写代码-既便宜又容易

此外,每个人都了解另一件事。为了使反应式编程真正展开,您需要整个系统(包括数据库)是反应式的。问题在于数据库甚至可能没有响应式或至少异步的API。是的,也许是这样的API,但您的驱动程序可能不支持它。

实际上,当我需要经典的关系数据库时,周围的几乎每个人都在开发PostgreSQL系统。话虽如此,默认选择。我们使用旧的(已有10多年历史的)JDBC驱动程序pgjdbc使用PostgreSQL这个驱动程序对每个人都有好处。几乎没有错误。此驱动程序的性能得到了极大的改善(为此,弗拉基米尔西尼科夫但是pgjdbc有一个致命的缺陷- 不支持异步API

近年来,一场激烈的竞赛开始为PostgreSQL开发替代驱动程序,其中包括异步API的开发。甚至Oracle都试图这样做,但是已经结束了对Loom项目及其Fibers的开发但是,Oracle对此进行了更好的考虑,然后重新开始

现在有3个解决方案:

  1. https://github.com/jasync-sql/jasync-sql-用Kotlin编写的PostgreSQL异步驱动程序,其中Netty是传输
  2. Vert.x使用的解决方案https://github.com/mauricio/postgresql-async值得注意的是,项目已存档,并且以前的jasync-sql驱动程序重写了相同的内容(尽管原始文件是用Scala编写的,而新的解决方案是用Kotlin编写的)。
    更新资料 我的评论已得到纠正,来自Vert.x客户端还活着,并且在基准测试中感觉很好
  3. Spring团队的驱动程序是https://github.com/r2dbc/r2dbc-postgresql该驱动程序立即提供一个响应式API(而非异步),并且像jasync-sql中一样,将Netty用于传输。

从概念上讲,这些驱动程序基于相似的原理。它们全部使用专有的PostgreSQL功能:


不幸的是,驱动程序无法更改Wire协议Postgres(好像Oleg Dokuk不想-https: //www.youtube.com/watch?v= n9tL2I_Big8 )。也就是说,Postgres仍然需要一个单独的Connection用于SELECT查询。此外,Postgres还在为每个Connection创建一个新流程-https: //www.postgresql.org/docs/current/tutorial-arch.html

但是,有个好消息。可以批量发送修改请求,而无需等待结果(使用管道)。在这种情况下,每个请求都不需要连接。

也就是说,总结一下。响应式(或异步)PG驱动程序改善了应用程序中的情况(我们现在使用基于Netty的非阻塞IO,而不是在查询上花费线程),但特别是在PostgreSQL方面-情况不是很好(希望改善网络协议和数据库架构) )

您应该更靠近哪个驱动器?如果像我一样在您的工作中使用Spring,那么r2dbc-postgresql可能是一个不错的选择。重要的是,在最新版本的框架中,Pivotal的人员必须很好地将驱动程序与通常的东西集成在一起,例如与Spring Data R2DBC(这仍然是RC)。结果,我们不必使用低级驱动程序API和连接池,从而减少了在如此复杂的项目中犯错的可能性。

使用Spring Data R2DBC的最小示例(我已经在文档中成功完成了侦探)看起来很熟悉:

1.配置凭证和连接池:

spring.r2dbc.username=postgres
spring.r2dbc.password=P4$$W0RddD
spring.r2dbc.url=r2dbc:postgresql://localhost:5432/r2dbc
spring.r2dbc.pool.enabled=true
spring.r2dbc.pool.initial-size=10
spring.r2dbc.pool.max-idle-time=1m
spring.r2dbc.pool.max-size=30
spring.data.r2dbc.repositories.enabled=true

2.创建一个实体:

public class Customer {
    @Id
    private Long id;

    private String firstName;

    private String lastName;

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

3.创建通常的存储库:

public interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> {
}

4.使用存储库:

@RestController
@RequestMapping("/")
public class CustomerController {

    private CustomerRepository customerRepository;

    @PostMapping("/customer")
    Mono<Void> create(@RequestBody Publisher<Customer> customerFlux) {
        return customerRepository.saveAll(customerFlux).then();
    }

    @GetMapping("/customer")
    public Flux<Customer> list() {
        return customerRepository.findAll();
    }

    @GetMapping("/customer/{id}")
    public Mono<Customer> findById(@PathVariable Long id) {
        return customerRepository.findById(id);
    }
}

可以在此存储库中找到完整的示例-https: //github.com/Hixon10/spring-boot-r2dbc-postgresql-example

最后,让我们谈谈重要的一点:您现在需要在应用程序中使用r2dbc吗?我认为-为时过早。我将等待一系列技术(驱动程序,Spring DATA)发布,并收集一些初衷。我认为,到2021年,将有可能更仔细地研究这个驱动因素。

当前的状态-整个反应系统(Spring WebFlux + R2DBC数据库驱动程序)看起来很酷。从字面上看ole发布了摘要,其中有指向具有基准的文章的链接-https: //technology.amis.nl/2020/04/10/spring-blocking-vs-non-blocking-r2dbc-vs-jdbc-and-webflux-vs- web-mvc /简而言之-反应性胜出。

All Articles