CockroachDB, MongoDB ve FerretDB’de Benzersiz Kısıtlamalarla Denemeler Yapma

In: Genel


Motivasyon

İlk iki makalemi tamamladıktan sonra, CockroachDB tarafından desteklenen FerretDB aracılığıyla MongoDB koleksiyonlarını proxy’ye almanın birçok olasılığı olduğunu fark ettim. CockroachDB, çok bölgeli soyutlamalar, ters çevrilmiş ve kısmi dizinler, hesaplanmış sütunlar ve elbette güçlü tutarlılık yoluyla sağlanan benzersiz veri yerleşimi yeteneklerine sahiptir. Bugün, MongoDB ve CockroachDB’deki benzersiz kısıtlamaları tartışacağız.

Üst Düzey Adımlar

  • 9 düğümlü çok bölgeli bir küme başlatın (CockroachDB Dedicated)
  • FerretDB’yi (Docker) başlatın
  • Benzersiz Dizinler
  • Hususlar
  • Çözüm

Adım adım talimatlar

9 Düğümlü Çok Bölgeli Küme Başlatın (Hamamböceği Adanmış)

Önceki makaledeki aynı CockroachDB Dedicated kümesini kullanacağım. Ayrıntılı adımlar için lütfen önceki makaleye bakın. Bunu takiben 30 günlük CockroachDB Dedicated deneme sürümü alabilirsiniz. bağlantı.

FerretDB’yi (Docker) başlatın

Bir önceki makaledeki aynı oluşturma dosyasını kullanacağım, ancak çoklu bölgeyi tartışacağımız için oluşturma dosyasında değişiklikler yapacağım ve aşağıdaki adımları tartışacağım.

Benzersiz Dizinler

FerretDB geliştirme aşamasındadır ve birçok özellik hala kullanılamayabilir. Önceki makalede, bir MongoDB’yi taşıdım sample_mflix bazı koleksiyonlar için benzersiz dizinlere dayanan veri kümesi. Bu yazı itibariyle, FerretDB’de benzersiz kısıtlamaların çalışmasını doğrulayamadım. Henüz uygulanmadığı sonucuna vardım. Tartışmak istediğimiz bazı yetenekleri engelliyor ve bunun yerine küresel olarak güçlü tutarlı benzersiz dizinler için CockroachDB’den nasıl yararlanabileceğimizi göstereceğim.

geri yükle sample_mflix.users toplama daha önce yapmadıysanız

mongorestore --archive=sampledata.archive --nsInclude=sample_mflix.users --numInsertionWorkersPerCollection=100

2022-09-12T16:29:24.266-0400    sample_mflix.users  28.9KB
2022-09-12T16:29:26.156-0400    sample_mflix.users  28.9KB
2022-09-12T16:29:26.156-0400    finished restoring sample_mflix.users (185 documents, 0 failures)
2022-09-12T16:29:26.200-0400    restoring indexes for collection sample_mflix.users from metadata
2022-09-12T16:29:26.200-0400    index: &idx.IndexDocument{Options:primitive.M{"name":"email_1", "unique":true, "v":2}, Key:primitive.D{primitive.E{Key:"email", Value:1}}, PartialFilterExpression:primitive.D(nil)}
2022-09-12T16:29:26.203-0400    185 document(s) restored successfully. 0 document(s) failed to restore.

veri kümesine bakarak verilerle birlikte benzersiz bir kısıtlamanın geri yüklendiğine dikkat edin tanımgerçekten de benzersiz bir kısıtlama var email alan. CockroachDB’deki şema, kısıtlamanın farkında değil:

 CREATE TABLE sample_mflix.users_5e7cc513 (                     
         _jsonb JSONB NULL,                                     
         rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
         CONSTRAINT users_5e7cc513_pkey PRIMARY KEY (rowid ASC) 
 );

Bu dosyayı tekrar geri yüklemeyi denersek, kısıtlama tetiklenmez, aslında mevcut satırlara eklenir.

Başlangıçta 185 kaydı geri yükledik, geri yüklemeyi yeniden çalıştırırsak 370 kayıt görmeliyiz

2022-09-12T16:38:01.207-0400    sample_mflix.users  28.9KB
2022-09-12T16:38:01.207-0400    finished restoring sample_mflix.users (185 documents, 0 failures)
2022-09-12T16:38:01.247-0400    restoring indexes for collection sample_mflix.users from metadata
2022-09-12T16:38:01.247-0400    index: &idx.IndexDocument{Options:primitive.M{"name":"email_1", "unique":true, "v":2}, Key:primitive.D{primitive.E{Key:"email", Value:1}}, PartialFilterExpression:primitive.D(nil)}
2022-09-12T16:38:01.251-0400    185 document(s) restored successfully. 0 document(s) failed to restore.

ferretdb=> select count(*) from sample_mflix.users_5e7cc513 ;
 count 
-------
   370

Benzersiz kısıtlamanın uygulanmadığı açıktır. FerretDB ne gösterir:

sample_mflix> db.getCollectionInfos(  )
[ { name: 'users', type: 'collection' } ]

sample_mflix> db.users.getIndexes()
MongoServerError: no such command: 'listIndexes'

Açıkça eklemeye çalışalım

sample_mflix> db.users.createIndex( { "email": 1 }, { unique: true } )
email_1

FerretDB kullanarak bir satır eklemeye çalışalım.

sample_mflix> db.users.findOne({ })
{
  _id: ObjectId("59b99db4cfa9a34dcd7885b6"),
  name: 'Ned Stark',
  email: 'sean_bean@gameofthron.es',
  password: '$2b$12$UREFwsRUoyF0CRqGNK0LzO0HM/jLhgUCNNIJ9RJAqMUQ74crlJ1Vu'
}

Aynı e-posta adresiyle başka bir kayıt ekleyeceğiz

sample_mflix> db.users.insertOne({name: 'Stark Sr.', email: 'sean_bean@gameofthron.es' })
{
  acknowledged: true,
  insertedId: ObjectId("631f99c3cc8ad2b643a9f459")
}

Ekleme kabul edildi

MongoDB’ye, benzersiz kısıtlamaların uygulanmasının gerçekten işe yaradığına dair şüphenin avantajını vereceğim. Buradaki sorunun FerretDB ile ilgili olduğunu düşünüyorum.

Kısıtlamayı CockroachDB tarafında uygulayalım:

JSONB alanındaki e-posta alanında hesaplanmış bir sütun oluşturmamız gerekecek, ayrıca belirtiyoruz UNIQUE komutun bir parçası olarak kısıtlama.

ALTER TABLE sample_mflix.users_5e7cc513 ADD COLUMN email STRING NOT NULL UNIQUE AS ((_jsonb->>'email')::STRING) VIRTUAL;

Ned Stark’ın e-posta adresini eklediyseniz veya önerdiğim gibi kullanıcıların koleksiyonunu iki kez geri yüklediyseniz, CockroachDB benzersiz kısıtlama ihlalini algılayacaktır.

ERROR:  failed to ingest index entries during backfill: duplicate key value violates unique constraint "users_5e7cc513_email_key"
DETAIL:  Key (email)=('sean_bean@gameofthron.es') already exists.

Tabloyu kısaltma veya tüm ihlalleri manuel olarak silme seçeneğiniz vardır.

TRUNCATE TABLE sample_mflix.users_5e7cc513 ;
ALTER TABLE sample_mflix.users_5e7cc513 ADD COLUMN email STRING NOT NULL UNIQUE AS ((_jsonb->>'email')::STRING) VIRTUAL;

Şema şimdi şöyle görünüyor:

CREATE TABLE sample_mflix.users_5e7cc513 (                           
         _jsonb JSONB NULL,
         rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
         email STRING NOT NULL AS (_jsonb->>'email':::STRING) VIRTUAL,
         CONSTRAINT users_5e7cc513_pkey PRIMARY KEY (rowid ASC),
         UNIQUE INDEX users_5e7cc513_email_key (email ASC)
 ) LOCALITY REGIONAL BY TABLE IN PRIMARY REGION;

Bu noktada koleksiyonu tekrar geri yüklemeyi deneyebiliriz, bu sefer CockroachDB benzersizliği email alan.

2022-09-14T12:43:59.689-0400    finished restoring sample_mflix.users (185 documents, 0 failures)
2022-09-14T12:43:59.715-0400    restoring indexes for collection sample_mflix.users from metadata
2022-09-14T12:43:59.715-0400    index: &idx.IndexDocument{Options:primitive.M{"name":"email_1", "unique":true, "v":2}, Key:primitive.D{primitive.E{Key:"email", Value:1}}, PartialFilterExpression:primitive.D(nil)}
2022-09-14T12:43:59.718-0400    185 document(s) restored successfully. 0 document(s) failed to restore.

kullanarak bir kayıt eklemeye çalışalım. mongosh

db.users.insertOne({name: 'Stark Sr.', email: 'sean_bean@gameofthron.es' })

MongoServerError: [pool.go:283 pgdb.(*Pool).InTransaction] [msg_insert.go:108 pg.(*Handler).insert.func1] [insert.go:57 pgdb.InsertDocument] ERROR: duplicate key value violates unique constraint "users_5e7cc513_email_key" (SQLSTATE 23505)

Bir ihlalimiz var! Ama sadece %100 emin olmak için, tabloyu tekrar geri yüklemeyi deneyelim.

2022-09-12T16:56:55.884-0400    Failed: sample_mflix.users: error restoring from archive 'sampledata.archive': (InternalError) [pool.go:283 pgdb.(*Pool).InTransaction] [msg_insert.go:108 pg.(*Handler).insert.func1] [insert.go:57 pgdb.InsertDocument] ERROR: duplicate key value violates unique constraint "users_5e7cc513_email_key" (SQLSTATE 23505)
2022-09-12T16:56:55.884-0400    0 document(s) restored successfully. 0 document(s) failed to restore.

Hususlar

Burada durabiliriz, ancak güçlü küresel tutarlılığa sahip çok bölgeli bir veritabanına sahip olmanın önemli faydaları olduğu için bu kavramı kalıcı kılmak istiyorum. Benzersiz kısıtlama, tüm bölgeler, kullanılabilirlik alanları ve düğümler genelinde oluşturulduktan hemen sonra uygulanır. Veri tabanına saydan erişecek olsaydık aws-us-east-2, aynı ihlali alırdık. FerretDB oluşturma ortamını parçalayalım ve üç yeni oluşturalım. mongosh istemciler, her biri bölgesel (aws-us-east-1, aws-us-east-2, aws-us-west-2) küme uç noktaları.

version: "3"
services:

  ferretdb-us-east-1:
    image: ghcr.io/ferretdb/ferretdb:latest
    hostname: 'ferretdb-us-east-1'
    container_name: 'ferretdb-us-east-1'
    restart: 'on-failure'
    command:
      [
        '-listen-addr=:27017',
        ## Dedicated multiregion cluster
        '-postgresql-url=postgresql://artem:password@artem-mr-7xw.aws-us-east-1.cockroachlabs.cloud:26257/ferretdb?sslmode=verify-full&sslrootcert=/certs/artem-mr-ca.crt'
      ]
    ports:
      - 27017:27017
    volumes:
       - /Users/artem/.postgresql/root.crt:/certs/root.crt
       - /Users/artem/Library/CockroachCloud/certs/artem-mr-ca.crt:/certs/artem-mr-ca.crt

  ferretdb-us-east-2:
    image: ghcr.io/ferretdb/ferretdb:latest
    hostname: 'ferretdb-us-east-2'
    container_name: 'ferretdb-us-east-2'
    restart: 'on-failure'
    command:
      [
        '-listen-addr=:27017',
        ## Dedicated multiregion cluster
        '-postgresql-url=postgresql://artem:password@artem-mr-7xw.aws-us-east-2.cockroachlabs.cloud:26257/ferretdb?sslmode=verify-full&sslrootcert=/certs/artem-mr-ca.crt'
      ]
    ports:
      - 27019:27017
    volumes:
       - /Users/artem/.postgresql/root.crt:/certs/root.crt
       - /Users/artem/Library/CockroachCloud/certs/artem-mr-ca.crt:/certs/artem-mr-ca.crt

  ferretdb-us-west-2:
    image: ghcr.io/ferretdb/ferretdb:latest
    hostname: 'ferretdb-us-west-2'
    container_name: 'ferretdb-us-west-2'
    restart: 'on-failure'
    command:
      [
        '-listen-addr=:27017',
        ## Dedicated multiregion cluster
        '-postgresql-url=postgresql://artem:password@artem-mr-7xw.aws-us-west-2.cockroachlabs.cloud:26257/ferretdb?sslmode=verify-full&sslrootcert=/certs/artem-mr-ca.crt'
      ]
    ports:
      - 27021:27017
    volumes:
       - /Users/artem/.postgresql/root.crt:/certs/root.crt
       - /Users/artem/Library/CockroachCloud/certs/artem-mr-ca.crt:/certs/artem-mr-ca.crt 

hizmetler oluşturdum ferretdb-us-east-1, ferretdb-us-east-2 ve ferretdb-us-west-2. Bağlantı dizeleri, ana bilgisayar bağlantı noktalarını ortaya çıkaran bölgesel uç noktalarla çakışır. 27017, 27019 ve 27021 sırasıyla. doğrulamak için çekinmeyin -postgresql-url hizmetlerin her biri için.

docker compose up -d
docker compose ps

NAME                 COMMAND                  SERVICE              STATUS              PORTS
ferretdb-us-east-1   "/ferretdb -listen-a…"   ferretdb-us-east-1   running             0.0.0.0:27017->27017/tcp
ferretdb-us-east-2   "/ferretdb -listen-a…"   ferretdb-us-east-2   running             0.0.0.0:27019->27017/tcp
ferretdb-us-west-2   "/ferretdb -listen-a…"   ferretdb-us-west-2   running             0.0.0.0:27021->27017/tcp

Her uç noktanın bölgesel örneğe eriştiğini gösterecek kadar Mongo CLI’ye aşina değilim, birazdan SQL’de göstereceğim. Bu arada bir kayıt eklemeye çalışalım

Erişmek mongosh işaret etmek aws-us-west-2 uç nokta

mongosh mongodb://localhost:27021

Kayıt ekle

sample_mflix> db.users.insertOne({name: 'Stark Sr.', email: 'sean_bean@gameofthron.es' })
MongoServerError: [pool.go:283 pgdb.(*Pool).InTransaction] [msg_insert.go:108 pg.(*Handler).insert.func1] [insert.go:57 pgdb.InsertDocument] ERROR: duplicate key value violates unique constraint "users_5e7cc513_email_key" (SQLSTATE 23505)

Başarısız oldu ve CockroachDB dizinlerinin coğrafyalar arasında tutarlı olduğunu kanıtlıyor. Bu noktaya değinmek için neden bu kadar çok çalıştığımı soruyor olabilirsiniz. MongoDB belgelerini okuyordum ve aşağıdakileri buldum Not:

Çoğaltma kümeleri ve parçalanmış kümeler için benzersiz bir dizin oluşturmak üzere yuvarlanan bir yordam kullanmak, yordam sırasında koleksiyona yapılan tüm yazmaları durdurmanızı gerektirir. Yordam sırasında koleksiyona yapılan tüm yazmaları durduramazsanız, yuvarlama yordamını kullanmayın. Bunun yerine, koleksiyonda benzersiz dizininizi şu şekilde oluşturun:

ihraç db.collection.createIndex() bir çoğaltma kümesi için birincil veya

ihraç db.collection.createIndex() parçalanmış bir küme için mongolarda.

Notu yanlış yorumluyorsam lütfen düzeltin, ancak MongoDB’de bir dizin oluşturduğunuzda koleksiyona yazmayı bırakmanız gerektiğini söylüyor. Ek olarak, yazmayı durdurmak bir seçenek değilse, üzerinde bir dizin oluşturmanız gerekir. mongos anladığım kadarıyla Mongo konuşmasındaki takipçi kopyaları. Bu kesinlikle CockroachDB için geçerli değildir ve CockroachDB tutarlılık garantilerine aykırıdır. Benzersiz dizin küreseldir ve tüm düğümler, kullanılabilirlik alanları ve bölgelerde tutarlıdır. Bir kez yaratırsınız ve masaya yazılanları durdurmazsınız. Bununla birlikte, size bu örneği SQL’de göstereyim.

şuraya bağlanayım aws-us-west-2 bölge ve kasıtlı olarak kısıtlamayı ihlal etmeye çalışmak

cockroach sql --url "postgresql://artem:password@artem-mr-7xw.aws-us-west-2.cockroachlabs.cloud:26257/ferretdb2?sslmode=verify-full&sslrootcert=$HOME/Library/CockroachCloud/certs/artem-mr-ca.crt"

Bölgeyi doğrulayalım

 gateway_region 
----------------
 aws-us-west-2

Ev sahibimden ağ gidiş dönüş süresini görelim

Time: 69ms total (execution 1ms / network 68ms)

Bu doğru görünüyor, New Jersey’de bulunduğum yerden yaklaşık 70ms RTT var.

Bir kayıt eklemeyi deneyelim

INSERT INTO sample_mflix.users_5e7cc513 ("_jsonb") VALUES (
    '{"email": "sean_bean@gameofthron.es"}'
  );

ERROR: duplicate key value violates unique constraint "users_5e7cc513_email_key"
SQLSTATE: 23505
DETAIL: Key (email)=('sean_bean@gameofthron.es') already exists.
CONSTRAINT: users_5e7cc513_email_key

Çözüm

Bu, MongoDB koleksiyonlarıyla yaptığımız benzersiz kısıtlama deneylerimizi tamamlıyor. FerretDB aracılığıyla proxy sağladığımız için bazı yeteneklerin MongoDB tarafında test edilmediğini kabul ediyorum. Ancak, sıkı şema doğrulaması olan uygun bir ilişkisel veritabanına sahip olmanın kullanıcıları veri kalitesi sorunlarından koruduğuna dair yeterli kanıt sunmuş olduğumu umuyorum. FerretDB ile yeni deneyler için sabırsızlanıyorum!

Önceki makaleler

FerretDB arka ucu için CockroachDB’yi kullanma
FerretDB ile MongoDB koleksiyonlarını CockroachDB’ye taşıma

Bir cevap yazın

Ready to Grow Your Business?

We Serve our Clients’ Best Interests with the Best Marketing Solutions. Find out More

How Can We Help You?

Need to bounce off ideas for an upcoming project or digital campaign? Looking to transform your business with the implementation of full potential digital marketing?

For any career inquiries, please visit our careers page here.
[contact-form-7 404 "Bulunamadı"]