Dokumen ini membandingkan Apache Cassandra dan Konsep dan praktik Spanner. Panduan ini mengasumsikan bahwa Anda sudah terbiasa dengan Cassandra dan ingin memigrasikan aplikasi yang ada atau mendesain aplikasi baru saat menggunakan Spanner sebagai database Anda.
Cassandra dan Spanner adalah database terdistribusi berskala besar dibangun untuk aplikasi yang membutuhkan skalabilitas tinggi dan latensi rendah. Meskipun keduanya dapat mendukung workload NoSQL yang berat, Spanner menyediakan fitur lanjutan untuk pemodelan data, kueri, dan operasional bisnis. Untuk mengetahui informasi selengkapnya tentang cara Spanner memenuhi kriteria database NoSQL, lihat Spanner untuk workload non-relasional.
Konsep inti
Bagian ini membandingkan konsep utama Cassandra dan Spanner.
Terminologi
Cassandra | Spanner |
---|---|
Cluster |
Instance Gugus Cassandra setara dengan Spanner instance - kumpulan server dan untuk semua resource penyimpanan. Karena Spanner adalah layanan terkelola, Anda tidak perlu mengkonfigurasi perangkat keras atau perangkat lunak yang mendasarinya. Anda hanya perlu menentukan jumlah node yang ingin dicadangkan untuk instance atau memilih penskalaan otomatis untuk menskalakan instance secara otomatis. Instance berfungsi seperti container untuk database, dan topologi replikasi data (regional, dual-region, atau multi-region) dipilih di level instance. |
Keyspace |
Database Keyspace Cassandra setara dengan Spanner database, yang merupakan kumpulan tabel dan elemen skema lainnya (misalnya, indeks dan peran). Tidak seperti keyspace, Anda tidak perlu mengkonfigurasi faktor replikasi. Spanner otomatis mereplikasi data Anda ke region yang ditentukan dalam di instance Compute Engine. |
Tabel |
Tabel Di Cassandra dan Spanner, tabel adalah kumpulan baris yang diidentifikasi dengan {i>primary key <i}yang ditentukan di skema tabel. |
Partisi |
Pisahkan Cassandra dan Spanner menskalakan dengan sharding data. Di Cassandra, setiap shard disebut partisi, sedangkan di Spanner, setiap shard disebut {i>split<i}. {i>Cassandra<i} menggunakan partisi {i>hash<i}, yang berarti bahwa setiap baris ditetapkan secara independen ke node penyimpanan berdasarkan {i>hash <i}dari kunci utama. Spanner dibagi rentangnya, artinya baris yang berdekatan di ruang kunci utama juga berdekatan dalam penyimpanan (kecuali di batas pemisahan). Spanner menangani pemisahan dan penggabungan berdasarkan beban dan penyimpanan, dan ini transparan pada aplikasi. Implikasi utama adalah bahwa tidak seperti Cassandra, pemindaian rentang pada awalan kunci utama adalah operasi yang efisien di Spanner. |
Baris |
Baris Di Cassandra dan Spanner, baris adalah kumpulan kolom diidentifikasi secara unik dengan {i>primary key<i}. Seperti Cassandra, Spanner mendukung kunci utama gabungan. Tidak seperti Cassandra, Spanner tidak membedakan antara kunci partisi dan kunci sortir, karena data di-sharding rentang. Kita dapat menganggap Spanner hanya memiliki kunci sortir, partisi yang dikelola di balik layar. |
Kolom |
Kolom Di Cassandra dan Spanner, kolom adalah kumpulan data nilai yang memiliki jenis yang sama. Ada satu nilai untuk setiap baris tabel. Untuk informasi lebih lanjut tentang membandingkan jenis kolom Cassandra dengan Spanner, lihat Jenis Data. |
Arsitektur
Cluster Cassandra terdiri dari sekumpulan server dan penyimpanan yang ditempatkan bersama dengan server tersebut. Fungsi {i>hash <i}memetakan baris dari ruang kunci partisi ke ruang {i>node<i} (vnode). Satu set vnode kemudian ditugaskan secara acak ke setiap server untuk melayani sebagian dari ruang kunci cluster. Penyimpanan untuk vnode terpasang secara lokal ke ke node inferensi. {i>Driver<i} klien terhubung langsung ke {i>node <i}layanan dan menangani load balancing dan perutean kueri.
Instance Spanner terdiri dari serangkaian server dalam topologi replikasi. Spanner secara dinamis melakukan sharding setiap tabel ke dalam rentang baris berdasarkan Penggunaan CPU dan disk. Shard ditetapkan ke node komputasi untuk inferensi. Data adalah secara fisik disimpan di Colossus, sistem file terdistribusi milik Google, terpisah dari ke node komputasi. Driver klien terhubung ke frontend Spanner server yang melakukan perutean permintaan dan load balancing. Untuk mempelajari lebih lanjut, lihat Bacaan Spanner & Menulis laporan resmi.
Pada level yang tinggi, kedua arsitektur menskalakan seiring resource ditambahkan ke cluster yang mendasarinya. Pemisahan komputasi dan penyimpanan Spanner memungkinkan penyeimbangan beban yang lebih cepat antara node komputasi sebagai respons terhadap perubahan beban kerja. Tidak seperti Cassandra, pemindahan shard tidak melibatkan pemindahan data karena data tetap berada di Colossus. Selain itu, partisi berbasis rentang Spanner mungkin lebih alami untuk aplikasi yang mengharapkan data diurutkan berdasarkan kunci partisi. Sisi lain dari partisi berbasis rentang adalah beban kerja yang menulis ke salah satu ujung ruang kunci (misalnya, tabel yang diberi kunci berdasarkan stempel waktu saat ini) mungkin mengalami hotspotting tanpa pertimbangan desain skema tambahan. Untuk informasi selengkapnya tentang teknik mengatasi hotspotting, lihat Praktik terbaik desain skema.
Konsistensi
Dengan Cassandra, Anda harus menentukan tingkat konsistensi untuk setiap operasi. Jika Anda menggunakan di tingkat konsistensi kuorum, mayoritas node replika harus merespons {i>node<i} koordinator untuk operasi yang akan dianggap berhasil. Jika Anda menggunakan level konsistensi satu, Cassandra memerlukan satu node replika untuk merespons agar operasi dianggap berhasil.
Spanner memberikan konsistensi yang kuat. Spanner API tidak mengekspos replika ke klien. Klien Spanner berinteraksi dengan Spanner seolah-olah merupakan database mesin tunggal. Tulisan adalah selalu ditulis ke sebagian besar replika sebelum dikonfirmasi kepada pengguna. Setiap pembacaan berikutnya mencerminkan data yang baru ditulis. Aplikasi dapat memilih untuk membaca {i>snapshot<i} dari {i>database<i} pada satu waktu di masa lalu, yang mungkin memiliki manfaat performa dibandingkan pembacaan yang kuat. Untuk informasi selengkapnya tentang konsistensi Properti Spanner, lihat Ringkasan transaksi.
Spanner dibuat untuk mendukung konsistensi dan ketersediaan yang dibutuhkan dalam aplikasi skala besar. Spanner memberikan kemampuan konsistensi dalam skala besar dan dengan performa tinggi. Untuk kasus penggunaan yang memerlukannya, Spanner mendukung pembacaan snapshot yang memenuhi persyaratan kesegaran.
Pemodelan data
Bagian ini membandingkan model data Cassandra dan Spanner.
Deklarasi tabel
Sintaksis deklarasi tabel cukup mirip di Cassandra dan Spanner. Anda menentukan nama tabel, nama dan jenis kolom, dan {i>primary key<i} yang secara unik mengidentifikasi baris. Perbedaan utamanya adalah Cassandra dipartisi hash dan membuat perbedaan antara kunci partisi dan kunci pengurutan, sedangkan Spanner dipartisi rentang. Spanner dapat dianggap sebagai hanya memiliki kunci sortir, dengan partisi secara otomatis dikelola di balik layar. Seperti Cassandra, Spanner mendukung kunci utama gabungan.
Satu bagian kunci utama
Perbedaan antara Cassandra dan Spanner terletak pada nama jenis dan lokasi klausa {i>primary key<i}.
Cassandra | Spanner |
---|---|
CREATE TABLE users ( user_id bigint, first_name text, last_name text, PRIMARY KEY (user_id) ) |
CREATE TABLE users ( user_id int64, first_name string(max), last_name string(max), ) PRIMARY KEY (user_id) |
Beberapa bagian kunci utama
Untuk Cassandra, bagian kunci utama yang pertama adalah "kunci partisi" dan bagian kunci utama berikutnya adalah "sort key". Untuk Spanner, tidak ada kunci partisi terpisah. Data disimpan dan diurutkan berdasarkan seluruh komposit {i>primary key<i}-nya.
Cassandra | Spanner |
---|---|
CREATE TABLE user_items ( user_id bigint, item_id bigint, first_name text, last_name text, PRIMARY KEY (user_id, item_id) ) |
CREATE TABLE user_items ( user_id int64, item_id int64, first_name string(max), last_name string(max), ) PRIMARY KEY (user_id, item_id) |
Kunci partisi gabungan
Untuk Cassandra, kunci partisi dapat berupa komposit. Tidak ada partisi terpisah di Spanner. Data disimpan dan diurutkan berdasarkan seluruh komposit {i>primary key<i}-nya.
Cassandra | Spanner |
---|---|
CREATE TABLE user_category_items ( user_id bigint, category_id bigint, item_id bigint, first_name text, last_name text, PRIMARY KEY ((user_id, category_id), item_id) ) |
CREATE TABLE user_category_items ( user_id int64, category_id int64, item_id int64, first_name string(max), last_name string(max), ) PRIMARY KEY (user_id, category_id, item_id) |
Jenis data
Bagian ini membandingkan jenis data Cassandra dan Spanner. Untuk mengetahui informasi selengkapnya tentang jenis Spanner, lihat Jenis data di GoogleSQL.
Cassandra | Spanner | |
---|---|---|
Jenis Numerik |
Bilangan bulat standar:bigint (bilangan bulat dengan tanda tangan 64-bit)int (bilangan bulat bertanda 32-bit)smallint (bilangan bulat dengan tanda tangan 16-bit)tinyint (bilangan bulat bertanda 8-bit)
|
int64 (bilangan bulat dengan tanda tangan 64-bit)Spanner mendukung jenis data lebar 64-bit tunggal untuk bilangan bulat yang ditandatangani. |
Floating point standar:double (floating point IEEE-754 64-bit)float (floating point IEEE-754 32-bit) |
float64 (floating point IEEE-754 64-bit)float32 (floating point IEEE-754 32-bit)
|
|
Angka presisi variabel:varint (bilangan bulat presisi variabel)decimal (desimal presisi variabel)
|
Untuk angka desimal presisi tetap, gunakan numeric (presisi 38 skala 9).
Jika tidak, gunakan string bersama dengan variabel lapisan aplikasi
library bilangan bulat presisi.
|
|
Jenis String |
text varchar
|
string(max) text dan varchar menyimpan serta memvalidasi string UTF-8. Di Spanner, kolom string harus menentukan panjang maksimumnya (tidak ada dampak pada penyimpanan; ini untuk tujuan validasi).
|
blob |
bytes(max)
Untuk menyimpan data biner, gunakan jenis data bytes .
|
|
Jenis Tanggal dan Waktu | date |
date |
duration |
int64
Spanner tidak mendukung jenis data durasi khusus. Gunakan int64 untuk menyimpan
dengan durasi nanodetik.
|
|
time |
int64
Spanner tidak mendukung jenis data waktu dalam hari khusus. Gunakan int64 untuk
menyimpan offset nanosekon dalam sehari.
|
|
timestamp |
timestamp |
|
Jenis Penampung | Jenis yang ditentukan pengguna | json atau proto |
list |
array Gunakan array untuk menyimpan daftar objek yang diketik.
|
|
map |
json atau proto Spanner tidak mendukung jenis peta khusus. Gunakan json atau proto
kolom yang mewakili peta. Untuk mengetahui informasi selengkapnya, lihat Menyimpan peta besar sebagai tabel sisipan.
|
|
set |
array
Spanner tidak mendukung jenis kumpulan khusus. Gunakan array kolom untuk mewakili
set , dengan aplikasi yang mengelola keunikan set. Untuk informasi selengkapnya, lihat Menyimpan peta besar sebagai tabel sisipan,
yang juga dapat digunakan
untuk menyimpan set besar.
|
Pola penggunaan dasar
Contoh kode berikut menunjukkan perbedaan antara kode klien Cassandra dan Spanner di Go. Untuk informasi selengkapnya, lihat library klien Spanner.
Inisialisasi klien
Di klien Cassandra, Anda membuat objek cluster yang mewakili cluster Cassandra, membuat instance objek sesi yang memisahkan koneksi ke cluster, dan mengeluarkan kueri pada sesi tersebut. Di Spanner, Anda membuat objek klien yang terikat ke database tertentu, dan mengeluarkan permintaan database pada objek klien.
Contoh Cassandra
Go
import "github.com/gocql/gocql" ... cluster := gocql.NewCluster("<address>") cluster.Keyspace = "<keyspace>" session, err := cluster.CreateSession() if err != nil { return err } defer session.Close() // session.Query(...)
Contoh Spanner
Go
import "cloud.google.com/go/spanner" ... client, err := spanner.NewClient(ctx, fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, instance, database)) defer client.Close() // client.Apply(...)
Membaca data
Operasi baca di Spanner dapat dilakukan melalui API gaya nilai kunci dan API kueri. Sebagai pengguna Cassandra, Anda mungkin merasa API kueri lebih familier. J
perbedaan utama dalam Query API adalah bahwa Spanner memerlukan
argumen bernama (tidak seperti argumen posisi ?
di Cassandra). Nama
dalam kueri Spanner harus diawali dengan @
.
Contoh Cassandra
Go
stmt := `SELECT user_id, first_name, last_name FROM users WHERE user_id = ?` var ( userID int firstName string lastName string ) err := session.Query(stmt, 1).Scan(&userID, &firstName, &lastName)
Contoh Spanner
Go
stmt := spanner.Statement{ SQL: `SELECT user_id, first_name, last_name FROM users WHERE user_id = @user_id`, Params: map[string]any{"user_id": 1}, } var ( userID int64 firstName string lastName string ) err := client.Single().Query(ctx, stmt).Do(func(row *spanner.Row) error { return row.Columns(&userID, &firstName, &lastName) })
Masukkan data
INSERT
Cassandra setara dengan INSERT OR UPDATE
Spanner.
Anda harus menetapkan kunci utama lengkap untuk penyisipan. Spanner mendukung DML dan API mutasi gaya nilai kunci. Gaya nilai kunci
mutation API direkomendasikan untuk operasi tulis sederhana karena latensi yang lebih rendah.
Spanner DML API memiliki lebih banyak fitur karena mendukung platform SQL lengkap (termasuk
penggunaan ekspresi dalam pernyataan DML).
Contoh Cassandra
Go
stmt := `INSERT INTO users (user_id, first_name, last_name) VALUES (?, ?, ?)` err := session.Query(stmt, 1, "John", "Doe").Exec()
Contoh Spanner
Go
_, err := client.Apply(ctx, []*spanner.Mutation{ spanner.InsertOrUpdateMap( "users", map[string]any{ "user_id": 1, "first_name": "John", "last_name": "Doe", } )})
Menyisipkan data dalam batch
Di Cassandra, Anda dapat menyisipkan beberapa baris menggunakan pernyataan batch. Di Spanner, operasi commit dapat berisi beberapa mutasi. Spanner menyisipkan mutasi ini ke database secara atomik.
Contoh Cassandra
Go
stmt := `INSERT INTO users (user_id, first_name, last_name) VALUES (?, ?, ?)` b := session.NewBatch(gocql.UnloggedBatch) b.Entries = []gocql.BatchEntry{ {Stmt: stmt, Args: []any{1, "John", "Doe"}}, {Stmt: stmt, Args: []any{2, "Mary", "Poppins"}}, } err = session.ExecuteBatch(b)
Contoh Spanner
Go
_, err := client.Apply(ctx, []*spanner.Mutation{ spanner.InsertOrUpdateMap( "users", map[string]any{ "user_id": 1, "first_name": "John", "last_name": "Doe" }, ), spanner.InsertOrUpdateMap( "users", map[string]any{ "user_id": 2, "first_name": "Mary", "last_name": "Poppins", }, ), })
Menghapus data
Penghapusan Cassandra memerlukan kunci utama baris yang akan dihapus.
Hal ini mirip dengan mutasi DELETE
di Spanner.
Contoh Cassandra
Go
stmt := `DELETE FROM users WHERE user_id = ?` err := session.Query(stmt, 1).Exec()
Contoh Spanner
Go
_, err := client.Apply(ctx, []*spanner.Mutation{ spanner.Delete("users", spanner.Key{1}), })
Topik lanjutan
Bagian ini berisi informasi tentang cara menggunakan fitur Cassandra lanjutan di Spanner.
Tulis stempel waktu
Cassandra memungkinkan mutasi menentukan stempel waktu tulis secara eksplisit untuk
sel tertentu menggunakan klausa USING TIMESTAMP
. Biasanya, fitur ini
digunakan untuk memanipulasi semantik
kemenangan penulis terakhir dari Cassandra.
Spanner tidak mengizinkan klien menentukan stempel waktu setiap
penulisan. Setiap sel ditandai secara internal dengan stempel waktu TrueTime pada
waktu saat nilai sel di-commit. Karena Spanner memberikan
konsisten dan dapat diserialisasi, sebagian besar aplikasi tidak memerlukan
fungsi USING TIMESTAMP
.
Jika Anda mengandalkan USING TIMESTAMP
Cassandra untuk logika khusus aplikasi, Anda dapat menambahkan
tambahan kolom TIMESTAMP
ke skema Spanner, yang dapat melacak waktu modifikasi pada
tingkat aplikasi. Pembaruan pada baris kemudian dapat digabungkan dalam transaksi
baca-tulis. Contoh:
Contoh Cassandra
Go
stmt := `INSERT INTO users (user_id, first_name, last_name) VALUES (?, ?, ?) USING TIMESTAMP ?` err := session.Query(stmt, 1, "John", "Doe", ts).Exec()
Contoh Spanner
Buat skema dengan kolom stempel waktu pembaruan eksplisit.
GoogleSQL
CREATE TABLE users ( user_id INT64, first_name STRING(MAX), last_name STRING(MAX), update_ts TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), ) PRIMARY KEY (user_id)
Sesuaikan logika untuk memperbarui baris dan menyertakan stempel waktu.
Go
func ShouldUpdateRow(ctx context.Context, txn *spanner.ReadWriteTransaction, updateTs time.Time) (bool, error) { // Read the existing commit timestamp. row, err := txn.ReadRow(ctx, "users", spanner.Key{1}, []string{"update_ts"}) // Treat non-existent row as NULL timestamp - the row should be updated. if spanner.ErrCode(err) == codes.NotFound { return true, nil } // Propagate unexpected errors. if err != nil { return false, err } // Check if the committed timestamp is newer than the update timestamp. var committedTs *time.Time err = row.Columns(&committedTs) if err != nil { return false, err } if committedTs != nil && committedTs.Before(updateTs) { return false, nil } // Committed timestamp is older than update timestamp - the row should be updated. return true, nil }
Periksa kondisi kustom sebelum memperbarui baris.
Go
_, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error { // Check if the row should be updated. ok, err := ShouldUpdateRow(ctx, txn, time.Now()) if err != nil { return err } if !ok { return nil } // Update the row. txn.BufferWrite([]*spanner.Mutation{ spanner.InsertOrUpdateMap("users", map[string]any{ "user_id": 1, "first_name": "John", "last_name": "Doe", "update_ts": spanner.CommitTimestamp, })}) return nil })
Mutasi bersyarat
Pernyataan INSERT ... IF EXISTS
di Cassandra setara dengan INSERT
di Spanner. Dalam kedua kasus tersebut, penyisipan akan gagal jika baris
sudah ada.
Di Cassandra, Anda juga dapat membuat pernyataan DML yang menentukan kondisi, dan
pernyataan akan gagal jika kondisi bernilai salah. Di
Spanner, Anda dapat menggunakan mutasi UPDATE
kondisional dalam transaksi baca-tulis. Misalnya, untuk memperbarui baris hanya jika
terdapat kondisi tertentu:
Contoh Cassandra
Go
stmt := `UPDATE users SET last_name = ? WHERE user_id = ? IF first_name = ?` err := session.Query(stmt, 1, "Smith", "John").Exec()
Contoh Spanner
Sesuaikan logika untuk memperbarui baris dan menyertakan kondisi.
Go
func ShouldUpdateRow(ctx context.Context, txn *spanner.ReadWriteTransaction) (bool, error) { row, err := txn.ReadRow(ctx, "users", spanner.Key{1}, []string{"first_name"}) if err != nil { return false, err } var firstName *string err = row.Columns(&firstName) if err != nil { return false, err } if firstName != nil && firstName == "John" { return false, nil } return true, nil }
Periksa kondisi kustom sebelum memperbarui baris.
Go
_, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error { ok, err := ShouldUpdateRow(ctx, txn, time.Now()) if err != nil { return err } if !ok { return nil } txn.BufferWrite([]*spanner.Mutation{ spanner.InsertOrUpdateMap("users", map[string]any{ "user_id": 1, "last_name": "Smith", "update_ts": spanner.CommitTimestamp, })}) return nil })
TTL
Cassandra mendukung penetapan nilai time to live (TTL) di tingkat baris atau kolom. Di Spanner, TTL dikonfigurasi di tingkat baris, dan Anda menetapkan sebagai waktu kedaluwarsa untuk baris. Untuk mengetahui informasi selengkapnya, lihat Ringkasan waktu tunggu (TTL).
Contoh Cassandra
Go
stmt := `INSERT INTO users (user_id, first_name, last_name) VALUES (?, ?, ?) USING TTL 86400 ?` err := session.Query(stmt, 1, "John", "Doe", ts).Exec()
Contoh Spanner
Membuat skema dengan kolom stempel waktu update yang eksplisit
GoogleSQL
CREATE TABLE users ( user_id INT64, first_name STRING(MAX), last_name STRING(MAX), update_ts TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), ) PRIMARY KEY (user_id), ROW DELETION POLICY (OLDER_THAN(update_ts, INTERVAL 1 DAY));
Menyisipkan baris dengan stempel waktu commit.
Go
_, err := client.Apply(ctx, []*spanner.Mutation{ spanner.InsertOrUpdateMap("users", map[string]any{ "user_id": 1, "first_name": "John", "last_name": "Doe", "update_ts": spanner.CommitTimestamp}), })
Menyimpan peta besar sebagai tabel sisipan.
Cassandra mendukung jenis map
untuk menyimpan pasangan nilai kunci yang diurutkan. Untuk menyimpan
jenis map
yang berisi data dalam jumlah kecil di Spanner, Anda
dapat menggunakan jenis JSON
atau PROTO
,
yang memungkinkan Anda menyimpan data semi-terstruktur dan terstruktur.
Pembaruan pada kolom tersebut mengharuskan seluruh nilai kolom ditulis ulang. Jika Anda
memiliki kasus penggunaan dengan data dalam jumlah besar yang disimpan di map
Cassandra, dan
hanya sebagian kecil map
yang perlu diperbarui, menggunakan
tabel INTERLEAVED
mungkin cocok. Misalnya, untuk menghubungkan sejumlah besar
data nilai kunci dengan pengguna tertentu:
Contoh Cassandra
CREATE TABLE users (
user_id bigint,
attachments map<string, string>,
PRIMARY KEY (user_id)
)
Contoh Spanner
CREATE TABLE users (
user_id INT64,
) PRIMARY KEY (user_id);
CREATE TABLE user_attachments (
user_id INT64,
attachment_key STRING(MAX),
attachment_val STRING(MAX),
) PRIMARY KEY (user_id, attachment_key);
Dalam hal ini, baris lampiran pengguna disimpan dan disimpan bersama baris pengguna, dan dapat diambil serta diperbarui secara efisien bersama dengan baris pengguna. Anda dapat menggunakan fungsi read-write API di Spanner untuk berinteraksi dengan tabel sisipan. Untuk selengkapnya informasi tentang interleaving, Membuat tabel induk dan turunan.
Pengalaman developer
Bagian ini membandingkan Spanner dan Cassandra alat developer lainnya.
Pengembangan lokal
Anda dapat menjalankan Cassandra secara lokal untuk pengembangan dan pengujian unit. Spanner menyediakan lingkungan serupa untuk pengembangan lokal melalui emulator Spanner. Emulator menyediakan lingkungan fidelitas rendah untuk pengembangan interaktif dan pengujian unit. Untuk selengkapnya informasi selengkapnya, lihat Mengemulasi Spanner secara lokal.
Command line
Spanner yang setara dengan nodetool
Cassandra adalah
Google Cloud CLI. Anda dapat melakukan
bidang kontrol dan data
operasi pesawat menggunakan gcloud spanner
. Untuk informasi selengkapnya, lihat
Panduan referensi Google Cloud CLI Spanner.
Jika Anda memerlukan antarmuka REPL untuk mengeluarkan kueri ke Spanner
mirip dengan cqlsh
, Anda dapat menggunakan alat spanner-cli
. Untuk menginstal dan menjalankan
spanner-cli
di Go:
go install github.com/cloudspannerecosystem/spanner-cli@latest
$(go env GOPATH)/bin/spanner-cli
Untuk mengetahui informasi selengkapnya, lihat repositori GitHub spanner-cli.