没有ACID数据库就可以进行交易(就数据一致性而言)?

时间:2018-05-04 14:03:42

标签: elasticsearch apache-kafka acid

我正在使用NodeJS,Kafka和Elasticsearch堆栈开展项目。我们有一个帐户微服务,需要确保帐户余额和交易的数据一致性(对某些客户来说,余额只能是负值)。

认为我们不需要实时交易结果,每个操作都可以异步处理,之后结果会显示给客户,有一些模型(如事件源,CQRS)提供数据没有ACID数据库的交易的一致性?

如果该模型只是做ACID数据库已经做的事情(并且做得很好),我们将实现一个SQL数据库(PostgreSQL)以适应这种情况。

3 个答案:

答案 0 :(得分:1)

这不是Elasticsearch的创建方式。虽然您可以在某种程度上使用事务和锁定,但它将保持“最终一致”数据库

您可以查看以下链接,了解elasticsearch中可用的内容:

https://www.elastic.co/blog/versioning

https://www.elastic.co/guide/en/elasticsearch/guide/current/concurrency-solutions.html

https://www.elastic.co/blog/found-elasticsearch-as-nosql

https://discuss.elastic.co/t/transactional-acid-features-in-es/5357/2

versioning的使用案例:

假设我们需要更新来自不同工作人员的资源。常见的方法是:

  1. 读取资源并获取其版本号
  2. 使用url中的读取版本号准备更新资源的请求
  3. 执行查询
    • 如果没有错误 - 我们完成了
    • 如果我们有错误转到1
  4. 在竞争条件下,只有第一个服务才会执行请求而不会出错。其他竞争对手必须尝试,直到他们成功。 Elasticsearch保证了这种交易的一致性。

    示例:

    # creating the resource, take a look on _version field
    # POST test/resources/42
    {
      "_index": "test",
      "_type": "resources",
      "_id": "42",
      "_version": 1,
      "result": "created",
      "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
      },
      "created": true
    }
    
    # reading the resource    
    # GET test/resources/1
    {
      "_index": "test",
      "_type": "resources",
      "_id": "1",
      "_version": 1,
      "found": true,
      "_source": {
        "value": 1
      }
    }
    
    # service number 1 trying to update the resource using version in url
    # POST test/resources/1?version=1
    # {...} 
    # response has new version
    {
      "_index": "test",
      "_type": "resources",
      "_id": "1",
      "_version": 2,
      "result": "updated",
      "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
      },
      "created": false
    }
    
    # service number 1 trying to update the resource -- fails
    # POST test/resources/1?version=1
    # {...}
    {
      "error": {
        "root_cause": [
          {
            "type": "version_conflict_engine_exception",
            "reason": "[resources][1]: version conflict, current version [2] is different than the one provided [1]",
            "index_uuid": "nQcwn90wQ9WauH9ySC7qEw",
            "shard": "3",
            "index": "test"
          }
        ],
        "type": "version_conflict_engine_exception",
        "reason": "[resources][1]: version conflict, current version [2] is different than the one provided [1]",
        "index_uuid": "nQcwn90wQ9WauH9ySC7qEw",
        "shard": "3",
        "index": "test"
      },
      "status": 409
    }
    

答案 1 :(得分:0)

是的,您可以执行transactional processing in Apache Kafkavid),并且您还可以使用kafka-connect-elasticseach连接器(more info)将数据幂等地置于Elastic。

答案 2 :(得分:0)

如果需要此功能,则可以遵循两阶段提交协议来模拟Elasticsearch中的事务,该协议涉及创建事务日志。这样可以确保所有事务完成或允许它们回滚。完整的说明可以在以下网址查看:https://alexmarquardt.com/2019/12/05/emulating-transactional-functionality-in-elasticsearch-with-two-phase-commits/