31 Ekim 2021 Pazar

DB Read Replicas CQRS

Giriş
Bu seviyede veri de iki kısma ayrılabilir. Açıklaması şöyle.
In a CQRS pattern, the Read data is separated out from the Write data. Read data can then be scaled out infinitesimally, and whenever there is a change in the Write data, its corresponding Read data has to be synchronized.
Açıklaması şöyle.
The implementation complexity increases and there is a major concept to be implemented:

model synchronization: synchronously or asynchronously, the events produced by the commands must trigger a refresh of the read database

Moreover, your event system has to be externalized for example as a message bus (Kafka, RabbitMQ). It will help you to safely keep your messages being processed.
Bir çok veri tabanı read replica için araçlar sağlar. Hatta bazılar consistency desteği bile veriyor. Açıklaması şöyle
Read Replicas provide different read database that contains a read only copy of the main write database.

The services can use different querying model in the code since the database structure is exactly same as write database.

This pattern is used to offload the write database from queries to balance the query traffic across one or more read instances.

Replication tools are usually provided by the DB vendors like IBM DB2, Oracle. Newer cloud-native, managed databases provided read replicas as managed service and takes care of replication and high availability of the read replicas.

In specialized cases the DB replication can also be tuned for strong consistency (aka a replication-factor). In which case the replication is done to favor strong consistency model (the C in the CAP). For example, AWS S3 provides strong read-after-write consistency model. Cassandra provides configurable read consistency levels settings.
Şeklen şöyle. Burada veri tabanı da iki kısma ayrılmış durumda. İkisi arasında senkronizasyon gerekiyor.

Senkronizasyon asenkron olduğu için "Eventual Consistency" oluşuyor. Şeklen şöyle

Açıklaması şöyle
In CQRS, when the write operation is persisted, an event is stored in event-store. This event is used to update the read store asynchronously. Events can also be replayed multiple times according to requirements to create different types of query stores.

As the read store is updated asynchronously at a later time, it will result in an Eventual consistent system. Eventual consistency provides high availability and better performance by sacrificing the strong consistency. CQRS will also eliminate the requirement for distributed transactions if eventual consistency can be accepted.
Böylece her iki veri tabanına Write ve Read API'ler ayrı ayrı verilebiliyor. Şeklen şöyle. Bu şekilde "Axon Framework" kullanılıyor
Diğer
Bu seviyede artık Event Publish ve CDC (Change Data Capture) da devreye girmeye başlıyor
Event Publish için açıklama şöyle. Command kodu veri tabanındaki değişikliği aynı zamanda bir kuyruğa yazar.
Many event-driven patterns compliment CQRS style applications. The command services write to a command database. So, any domain event that changes the state of the domain is a command and is written to a database optimized for writes. Command database may also be read for a read-before-write case transitionally, but that is usually within a small context of an aggregate. 

In addition, the command service also publishes the command into a messaging system and a command event with canonical event structure.

This event can be subscribed by any service and in this case, a query service subscription listens to the event and builds a local database that is optimized for reads. As opposite to DB replication, this approach provides the freedom to project the event in any read-optimized way. Indeed, event the choice of underlying database can be different from the command database, thus enabling a polyglot persistent.


App Centric Read and Write Model CQRS

Level 1: CQS: Command and Query Segregation
Açıklaması şöyleCommand Örüntüsü yazısına bakabilirsiniz.
This part is easy to understand. In your code, you should distinguish read and write operations and avoid mixed ones as much as possible. Your write operations should follow the Command design pattern.

I also recommend implementing a Command Bus interface that will work for the next maturity levels.
Level 2: Read and Write Model
Açıklaması şöyle. Burada iki farklı "code repository" durumundan da bahsediliyor, iki farklı repository olmak zorunda değil.
The second level of maturity requires to have two different models (and possibly repositories): the read model and the write model.

The architecture keeps a single data storage.

The read model is optimized to returns directly the data required by the API. For example, you are using Spring JDBC or MyBatis for the read model and Hibernate for the write model.

The write model is created by following the actions required by the business. Each command is a business use-case or operation.

The BDD or TDD approach will help you to build the necessary commands.

The execution of the commands may trigger events. The event bus and the event loop are stored into the memory of the server. Nothing complicated there.
Açıklaması şöyle. Halen aynı veri tabanı kullanıldığı için Consistency çok problem olmuyor
In a simple form to implement the theme of CQRS, applications are designed to create different read and write services & models to provide a clear module sub-boundary between these operations. The command service executes the writes in a database. The query service reads from the same database but produces a different query model that is purposed, for example for display in UI. Query model can make choice of transformation and projection of this data.

The underlying database remains the same, so the DB constrains & schema are still in force in both.

Since the underlying database is the same, DB consistency is strong (*).

As an example, the ORM frameworks, among other things create an “Object-Mapping” that lets a developer treat objects as entities and often has all the “entity-operations” abstracted out in the same entity class. While this has been working well in simple cases, it does not provide a design for different read and write models and services and two are treated as implementations of CRUD operations in the same entity class.

*Also depends on the Isolation settings of the DB. Consistency here is mapped to the Isolation in ACID properties (not the C in ACID)
Şekil olarak şöyle. Burada halen aynı veri tabanı kullanılıyor ancak kod iki kısma ayrılmış durumda

git push seçeneği - Değişiklikleri Uzak Depoya Gönderir

Giriş
Yapılmış olan değişiklikleri uzak depoya gönderilmek içindir. Açıklaması şöyle.
git push: Updates remote refs using local refs, while sending objects necessary to complete the given refs.
Örnek
Şöyle yaparız. Açıklaması şöyle
master is the default local branch in GIT (like we have svn trunk)
yerel depodaki master dalını uzak depodaki origin'e göndermek için şöyle yaparız
git push origin master
--follow-tags seçeneği
İlk defa burada gördüm. Ne olduğunu tam anlamadım. Açıklaması şöyle
And for each new release after that just omit the first-release option from the command. By running

git push --follow-tags
You push the newly created tag to your repository along with your changelog and the updated version number.
--force seçeneği
Örnek

Şöyle yaparız. Mevcut dosyanın üzerine yazmak için kullanılır.
git push --force origin master
-d/delete remote branch
Örnek - yeni yöntem
Yeni git ile söz dizimi şöyle
$ git push <remote_name> --delete <branch_name>
Şöyle yaparız
$ git push --delete origin feature/RLWY-2683_backup
Şöyle yaparız
git push -d <branchName>
Örnek - eski yöntem
Eski git ile söz dizimi şöyle
$ git push <remote_name> :<branch_name>
Şöyle yaparız
git -c push origin :feature/RLWY-2683_backup
-	:refs/heads/feature/RLWY-2683_backup	[deleted]
-u seçeneği
Uzak depoda kullanılacak branch ismini belirtir. Yeni bir bir branch açabilir

Örnek

Şöyle yaparız. Burada kısa ismi "origin" olan uzak depoya master isimli branch açılıyor.
git push -u origin master
Örnek
Eğer uzak depoda üzerinde master yoksa şöyle bir hata alırız
$ git push -u origin master
git@gitlab.com: Permission denied (publickey,keyboard-interactive).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Şöyle yaparız. remote -v uzak depoyu listeler. Daha sonra yerel depoyu uzak depoya bağlarız
$ git remote -v
origin git@gitlab.com:mdimas.umb/ewallet-app.git (fetch)
origin git@gitlab.com:mdimas.umb/ewallet-app.git (push)

$ git remote set-url origin https://gitlab.com/mdimas.umb/ewallet-app.git
git  status
git add .
git push -u origin master

Örnek
Şöyle yaparız
git push -u origin branch_name









24 Ekim 2021 Pazar

Apache Kafka Partition ve Global Event Order/Message Order

1. Global Event Order/Message Order
Normalde Kafka ile Global Event Order/Message Order korunamıyor.

Tek Consumer Olsaydı
Eğer tek bir consumer olsaydı mesajların sırası kaybolmazdı, ancak genellikle mesajlar partition şeklinde dağıtıldığı ve bunları işlemek için bir "Consumer Group" kullanıldığı için mesajların sırası kaybolabilir. Şeklen şöyle



Yani Topic dağıtıldığı için "Global Event Order" kaybedilir. Ancak partition 'lar kendi içinde sıralamayı korurlar. Açıklaması şöyle
A partition is an actual storage unit of Kafka messages which can be assumed as a Kafka message queue. The number of partitions per topic are configurable while creating it. Messages in a partition are segregated into multiple segments to ease finding a message by its offset. The default size of a segment is very high, i.e. 1GB, which can be configured.
Çözüm
1. Tek bir iş ile alakalı mesajlar aynı partition 'a konulur. Partition içinde sıralama korunduğu için sorun olmaz. Şeklen şöyle

2. Message Priority
Normalde Kafka ile Message Priority sağlanamıyor.

Çözüm
1. Her öncelik için kuyruk oluşturmak
Açıklaması burada

2. The Resequencer Pattern:
Açıklaması burada

3. The Bucket Priority Pattern
Açıklaması burada





22 Ekim 2021 Cuma

Wide-Column Veri Tabanları

Giriş
Açıklaması şöyle. Her satır farklı sütunlara sahip olabilir.
A wide-column store like Apache Cassandra or ScyllaDB allows rows (as minimal units of replication, analogous to rows as records in Postgres) to store a great, but most importantly, variable number of columns.
Veriye Erişim
Açıklaması şöyle
How you are going to fetch your data is one of the main ways to find the best database for your use case. If you are going to fetch data by key, then all you need is a key-value store (e.g. DynamoDB, Redis, S3, GCS).

In case you mostly fetch via key, but sometimes you also need to fetch by one or two other fields, then Wide-Column DBs (e.g.DynamoDB, Cassandra) may be right for you.

On the other hand if you will require to query by many different fields you can choose either Relational DB (e.g.MySQL, PostgreSQL) or Document DB (e.g.MongoDB, CouchDB, MySQL, PostgreSQ). Note that Document DBs don’t support well queries that require joining data from multiple documents.
Yani 
- Veriye eğer sadece key ile erişeceksek Key-Value Store kullanılabilir.
- Eğer veriye bir veya birkaç alana ile erişeceksek Wide-Column veri tabanı kullanılabilir.
- Eğer veriye herhangi bir  alan ile erişeceksek Relational (İlişkisel) veya Document veri tabanı kullanılabilir.

Document vs Wide Column Veri Tabanları
Her ikisi de esnek schema yeteneği sağlıyor. Ancak aralarında bir fark var
Wide Column Database şu işler için iyidir
- Frequent Writes. Yani infrequent update ve read anlamına gelir.
- Can Handle Large Data
- Not Suitable for Complex Queries

Document Database şu işler için iyidir
- Faster read. Sebebi ise Data denormalization kullanılması
- Not Suitable for Complex Queries

20 Ekim 2021 Çarşamba

gRPC Unary Service

Giriş
- Cevap olarak döndürülecek nesneyi Builder yardımıyla yaratırız.
- Daha sonra responseObserver.onNext() çağrısına cevap nesnesini geçeriz.
- En son olarak ta responseObserver.OnCompleted() çağrısını yaparız

Örnek
Elimizde şöyle bir servis olsun
import com.grpc.hello.grpc.HelloGrpc.HelloImplBase;
import com.grpc.hello.grpc.HelloReply;
import com.grpc.hello.grpc.HelloReply.Builder;
import com.grpc.hello.grpc.HelloRequest;

import io.grpc.stub.StreamObserver;

public class HelloService extends HelloImplBase {
  @Override
  public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
    Builder response = HelloReply.newBuilder();

    String caller = request.getName();
    String greet = "Hello " + caller;
    response.setMessage(greet);
    responseObserver.onNext(response.build());
    responseObserver.onCompleted();
  }
}
Örnek
Şöyle yaparız
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {

  String greeting = ...;

  HelloResponse response = HelloResponse.newBuilder()
    .setGreeting(greeting)
    .build();

  responseObserver.onNext(response);
  responseObserver.onCompleted();
}
Örnek - Hata Durumu
Şöye yaparız. Burada io.grpc.StatusException döndürülüyor
public class ProductService extends ProductServiceGrpc.ProductServiceImplBase { private final ProductRepository productRepository; public ProductService() { this.productRepository = new ProductRepository(); } @Override public void getProduct( GetProductRequest request, StreamObserver<GetProductResponse> responseObserver) { var productId = request.getProductId(); //Fetch Product information from repository Optional<Product> optionalProduct = productRepository.get(productId); if (optionalProduct.isPresent()) { var product = optionalProduct.get(); //If found build response var productResponse = Service.Product.newBuilder() .setName(product.getName()) .setDescription(product.getDescription()) .setPrice(product.getPrice()) .build(); var getProductResponse = GetProductResponse.newBuilder() .setProduct(productResponse).build(); responseObserver.onNext(getProductResponse); responseObserver.onCompleted(); } else { responseObserver.onError(new StatusException(Status.NOT_FOUND)); } log.info("Finished calling Product API service.."); } }

gRPC Server

Başlatma
- Önce bir tane io.grpc.Server nesnesi yaratmak gerekir. nesneyi yaratmak  için io.grpc.ServerBuilder veya io.grpc.netty.NettyServerBuilder kullanılır
- Servislerimizi addService() çağrısı ile ekleriz. 
- server.start() çağrısı ile server başlatılır
- En son server.awaitTermination() çağrısı ile beklenir

Durdurma
-shutdown() çağrısı server durdurma işlemi başlatılır. awaitTermination() ile durdurma işleminin bitmesi beklenir.


gRPC Gradle Plugin

Örnek
build.gradle dosyasında şöyle yaparız. Üretilen gRPC dosyalarını projeye dahil etmek için sourceSets bloğu kullanılır
plugins {
  id 'java'
  id "com.google.protobuf" version "0.8.12"
}

dependencies {
  //gRPC dependencies
  implementation 'com.google.protobuf:protobuf-java:3.17.3'
  implementation 'io.grpc:grpc-all:1.40.1'
  implementation 'javax.annotation:javax.annotation-api:1.3.2'
  ...
}

sourceSets {
  main {
    java {
      srcDirs 'build/generated/source/proto/main/grpc'
      srcDirs 'build/generated/source/proto/main/java'
    }
  }
}

protobuf {
  protoc {
    artifact = 'com.google.protobuf:protoc:3.12.4'
  }
  plugins {
    grpc {
      artifact = 'io.grpc:protoc-gen-grpc-java:1.31.0'
    }
  }
  generateProtoTasks {
    all()*.plugins {
      grpc {}
    }
  }
}

gRPC Unary

Örnek
Elimizde şöyle bir proto dosyası olsun
syntax = "proto3";
package dev.techdozo.product.api;

service ProductService {
  // A simple RPC.
  // returns Product for a given id
  rpc GetProduct(GetProductRequest) returns (GetProductResponse);
}

message GetProductRequest {
  string product_id = 1;
}

message GetProductResponse {
  Product product = 1;
}

message Product {
  string name = 1;
  string description = 2;
  double price = 3;
}

18 Ekim 2021 Pazartesi

Elasticsearch URI API

Giriş
URI kullanarak Elasticsearch'e erişim mümkün. API başlıkları şöyle
Document API
Search API
Indices API
cat API
Ingest API
Cluster API
Search API
Bu arama yöntemi REST + JSON yöntemine göre biraz daha kısıtlı. Açıklaması şöyle
Although the URI search is a simple and efficient way to query your cluster, you’ll quickly find that it doesn’t support all of the features ES offers. The full power of Elasticsearch is evident through Request Body Search. Using Request Body Search allows you to build a complex search request using various elements and query clauses that will match, filter, and order as well as manipulate documents depending on multiple criteria.
Örnek
Şöyle yaparız
“localhost:9200/_search?q=name:john~1 AND (age:[30 TO 40} OR surname:K*) AND -city”
Ingest API
Örnek - Insert
Şöyle yaparız
curl -XPUT -H "Content-Type: application/json" 
  http://localhost:9200/employee/_doc/1000?pretty -d '
{
"name": "Steve",
"age": 23,
"experienceInYears": 1
}'
{
  "_index" : "employee",
  "_type" : "_doc",
  "_id" : "1000",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
Örnek - Update
Şöyle yaparız
curl -XPOST -H "Content-Type: application/json"alo 
http://localhost:9200/employee/_doc/1000/_update?pretty -d '
{
"doc" : {
   "name": "Smith"
  }
}'
{
  "_index" : "employee",
  "_type" : "_doc",
  "_id" : "1000",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
Örnek - Delete
Şöyle yaparız
curl -XDELETE -H "Content-Type: application/json" 
  http://localhost:9200/employee/_doc/1000?pretty

{
  "_index" : "employee",
  "_type" : "_doc",
  "_id" : "1000",
  "_version" : 3,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

Elasticsearch Index

Giriş
Açıklaması şöyle. Namespace gibi düşünülebilir.
You can think of an index in Elasticsearch as a database in the world of relational databases. To add data to Elasticsearch, we need to create an index. In reality, an index is just a logical namespace, data actually divided and stored into many shards. All data-related operations like CRUD perform on shards instead of index, index acts as a representative for hiding complexity.
Örnek
Şöyle yaparız. Burada ismi employee olan iki tane shard'dan oluşan ve her bir shard'ın iki tane replicası olan bir index yaratıyoruz
curl -XPUT -H "Content-Type: application/json" http://localhost:9200/employee?pretty -d '
{
"settings": {
   "index": {
         "number_of_shards": 1,
         "number_of_replicas": 1
         }
      },
   "mappings": {
       "properties": {
         "age": {
               "type": "long"
         },
         "experienceInYears": {
               "type": "long"      
         },
         "name": {
               "type": "text"
         }
     }
   }
 } 
}'

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "employee"
}

11 Ekim 2021 Pazartesi

ACID - Isolation - Transaction'ların Birbirlerini Etkilememesi

Isolation Nedir
Transaction'ların birbirlerini etkilememesi anlamına gelir. Designing Data Intensive Applications kitabındaki açıklama şöyle.
Most databases are accessed by several clients at the same time. That is no problem if they are reading and writing different parts of the database, but if they are accessing the same database records, you can run into concurrency problems (race conditions).
...
Isolation in the sense of ACID means that concurrently executing transactions are isolated from each other: they cannot step on each other’s toes. The classic database textbooks formalize isolation as serializability, which means that each transaction can pretend that it is the only transaction running on the entire database. The database ensures that when the transactions have committed, the result is the same as if they had run serially (one after another), even though in reality they may have run concurrently.

However, in practice, serializable isolation is rarely used, because it carries a performance penalty. Some popular databases, such as Oracle 11g, don’t even implement it. In Oracle there is an isolation level called “serializable,” but it actually implements something called snapshot isolation, which is a weaker guarantee than serializability
Isolation Seviyeleri Nedir
ACID içindeki isolation seviyesi ve performans arasında bir seçim yapmak gerekiyor. Bu yüzden veri tabanları isolation seviyesini kontrol edebilmek için imkan tanıyorlar.
Seviyeler en güçlüden en zayıfa doğru şöyle
- Serializable
- Repeatable Read
- Read Committed
- Read Uncommitted
- Oracle default isolation level olarak "Read Committed" kullanıyor. SQL Server da aynı seviyeyi kullanıyor. Bu seviyede her iki veri tabanı için Non-Repeatable Read ve Phantom Read hataları olabilir.

- InnoDB ise ise default isolation level olarak repeatable read seviyesini kullanıyor. Bu seviyede nonrepeatable read hatası olmazken phantom read hataları halen olabiliyor.

Isolation Level ve Çözdükleri Problemler (Anomaly)
Şeklen şöyle. Burada Snapshot diye SQL Server'a özel bir isolation level daha gösteriliyor.


Read Committed Seviyesi Nedir?
Read Committed Nedir yazısına taşıdım.

Repeatable Read Seviyesi Nedir ?
Repeatable Read Nedir yazısına taşıdım.

Serializable Seviyesi Nedir ?
Serializable Nedir? yazısına taşıdım.

Ayrıca anomaliler için 
Lost Update Problem
Phantom Read

yazılarına bakabilirsiniz.












Multiple Dispatch

Giriş
Multiple dispatch çoğu programla dilinde yoktur. Açıklaması şöyle
This is a form of polymorphism. You can compare it to subtype polymorphism of the kind offered by OOP languages that support class inheritance. Those languages usually resorts to single dispatch, at runtime, to choose an implementation to satisfy a virtual call. Single dispatch in this case is based on the type of the object at runtime (a single value). Multiple dispatch can choose which way to go based on multiple values. You have a function type, multiple implementations and we polymorphically choose one at runtime based on one of multiple acceptable values, hence multiple dispatch.

In languages that support multi-methods (e.g. Clojure), this is not a problem at all because the language itself can express this relationship between a specific value and a function that needs to be called for it.
C#
C#'ta dynamic kelimesi ile nesnenin gerçek tipi kullanılabilir. 

Örnek
Elimizde şöyle bir hiyerarşi olsun
abstract class SpaceObject
{
    public SpaceObject(int size) => Size = size;

    public int Size { get; }
}

class Asteroid : SpaceObject
{
    public Asteroid(int size) : base(size) { }
}

class Spaceship : SpaceObject
{
    public Spaceship(int size) : base(size) { }
}
Bu hiyerarşiyi kullanan şöyle bir kod olsun. Burada "as dynamic" ile nesne gerçek tipine döndürülüyor. Eğer iki nesne de büyükse "Big boom!" yazar, eğer iki nesne de küçükse parametre tipleriner göre doğru metod çağrılır.
static class Collider
{
  public static string Collide(SpaceObject x, SpaceObject y) =>
        ((x.Size > 100) && (y.Size > 100)) ?
            "Big boom!" : CollideWith(x as dynamic, y as dynamic);
  private static string CollideWith(Asteroid x, Asteroid y) => "a/a";
  private static string CollideWith(Asteroid x, Spaceship y) => "a/s";
  private static string CollideWith(Spaceship x, Asteroid y) => "s/a";
  private static string CollideWith(Spaceship x, Spaceship y) => "s/s";
}
Bu hiyerarşiyi kullanan şöyle bir kod olsun
Collider.Collide(new Asteroid(101),  new Spaceship(300)));
Collider.Collide(new Asteroid(10),   new Spaceship(10)));
Collider.Collide(new Spaceship(101), new Spaceship(10)));

9 Ekim 2021 Cumartesi

Multi-Region/Multi-Node Veri Tabanı

Giriş
Multi-Region Veri Tabanları çeşit çeşit. Aralarındaki en temel fark ise hangi  replication yöntemini kullandıkları. Temelde 2 farklı replication yöntemi var. Açıklaması şöyle
Replication is the process of sharing/storing information in multiple places to ensure reliability, fault tolerance, and accessibility. The replication options are described as follows:

1. Active/passive replication - Daha basit olanı
2. Active/active replication
NotOpen-Source Data Replication Tools yazısında replication için kullanılabilecek bazı araçlar var.

1. Single Node Veri Tabanı
Multi-region çalışan veri tabanlarına bakmadan önce single node göz atmak gerekir. Bu konudaki bazı notlarım şöyle

1. Yedek Alınması
Şeklen şöyle. Tek bir veri tabanı varsa, bunun yedeğinin alınması active/passive veya active/active sistem olduğu anlamına gelmez

Açıklaması şöyle
The most basic deployment is a single-site single-node architecture. This does not give you anything in terms of business continuity. It provides no High availability and the only DR mechanism is to restore your database from a backup file. This type of deployment is normally seen in less critical environments such as development or used in CI/CD Pipelining technologies when testing is automated as part of that process. Nearly all databases can be deployed in this manner including CockroachDB, Oracle, SQL Server, etc.

2. Multi-Node Veri Tabanı - Active/Passive Yöntem
Şeklen şöyle

Açıklaması şöyle. Bu yöntemde primary tek bir veri tabanı var. Replica veri tabanlarından her hangi birisi primary yapılabiliyor.
In this model, there is a single master node and x number of passive nodes. This means that if there is an issue with the master node the application can be pointed at a secondary node and the secondary node can be promoted as a master, This is typically automatic but does involve downtime as the application repoints to the new node. This makes recovering from failure a lot faster than a single node architecture but still not a perfect solution for production deployments. Examples of databases that run in active-passive configurations are Oracle, SQL Server, MySQL, and Postgres.
Benim Active-Passive için incelediğim bazı ürünler şöyle

Vitess
Açıklaması şöyle. Vitess çözümünde aslında tarif edilen şey "multi-cell with 2 data centers". Yani bir primary herhangi bir region içinde. Replicalar ise her iki region içinde. High availability adına da her region içinde "cell" veya "availability zone" olarak tabir edilen farklı donanımlar üzerinde koşan veri tabanları kullanılıyor.
No active-active replication 
Vitess doesn’t support active-active replication setup (previously called multi-master). It has alternate ways of addressing most of the use cases that are typically solved by such a configuration.

Scalability: There are situations where active-active gives you a little bit of additional runway. However, since the statements have to eventually be applied to all writable servers, it’s not a sustainable strategy. Vitess addresses this problem through sharding, which can scale indefinitely.

High availability: Vitess integrates with Orchestrator, which is capable of performing a failover to a new primary within seconds of failure detection. This is usually sufficient for most applications.

Low-latency geographically distributed writes: This is one case that is not addressed by Vitess. The current recommendation is to absorb the latency cost of long-distance round-trips for writes. If the data distribution allows, you still have the option of sharding based on geographic affinity. You can then setup primarys for different shards to be in different geographic location. This way, most of the primary writes can still be local.

3. Multi-Node Veri Tabanı - Active/Active Yöntem
Açıklaması şöyle
In this model, all the nodes in the cluster are available for read and write operations. There is no concept of a master and secondary nodes as all nodes are equal within a multi-active cluster. This gives you a lot of benefits and control over HA and DR capabilities. It also has the inherent ability to allow ease of scalability. Databases that can be deployed in this category include CockroachDB, Cassandra, and Couchbase.
Açıklaması şöyle. Yani farklı bölgelerde çalışan active/active veri tabanları var.
Replicating data in multiple regions around the globe is a key way to solve a lot of potential headaches with globally distributed applications. Not only does it reduce latency for local end users, but if something goes wrong, you’ve got the redundancy required to increase availability, ensure business continuity and support disaster recovery plans.

Accomplishing this data replication requires an active/active database deployed across multiple regions or data centers. Most distributed databases are active/passive, where there is one primary database that serves both reads and writes, and the remaining database instances are read-only. In an active/active database, all the instances can accept read and write requests. There’s one database, but it’s distributed with data replicated across multiple regions, typically deployed in a cloud provider. Regions can cross continents or be within one country.
Active/Active Yöntem ihtiyacı için bazı sebepler şöyle
1. Disaster recovery
2. Data sovereignty : Bazı ülkeler verinin kendi topraklarında olmasını istiyor.
3. Latency reduction

Benim Active-Active için incelediğim bazı ürünler şöyle

Apache Cassandra
Apache Cassandra Multi-Region Active/Active Veri Tabanı olarak çalışabilir.

GridGain
Açıklaması şöyle
Data Replication Modes
GridGain supports active-passive and active-active modes for replication.

In the active-passive mode, only one cluster (the master) interacts with the user application, and the other cluster (the replica) stores data purely for redundancy and failover purposes.

In the active-active mode, both clusters handle user requests independently and propagate changes to each other. In this mode, care must be taken to resolve conflicts between updates that happen on the same cache entry in both clusters. For more information on how to resolve conflicts, refer to the Conflict Resolution section.
Active/Active Yöntem için Bazı problemler
1. Primary Key Problemi
Eğer primary key için sequence kullanılıyorsa sayılar çakışabilir.

2. Veri Tabanındaki Trigger
Replication ile gelen veri için trigger'ların çalışmaması istenebilir.

3. Cascade Constraints
Örnek ver

4. Data Collision
İki taraf aynı anda aynı veriyi değiştirmek isteyebilir.

Örnek
Burada bir öneri var. Tüm dünyadan gelen istekleri ilk geleni işleyecek şekilde bir ister var. "Sneakers drop" yapılıyor. Bunun için Active-Active multi-region kullanılıyor.

4. Multi-Node Veri Tabanlarının Bazı Sıkıntıları
En önemli sıkıntı region'lar arasındaki ağdan kaynaklanan gecikme. Şeklen şöyle. Burada aynı bölgede çalışan "East" düğümleri arasında gecikme çok az. Ancak East ve South arasındaki gecikme daha fazla. Central ve South arasındaki gecikme çok çok daha fazla.
Örneğin Vitess bir shard için tek bir master'a sahip olduğundan, eğer master bizim bölgemizde değilse, yazma işlemi yavaş kalabiliyor.