1 poin oleh GN⁺ 2024-08-11 | 1 komentar | Bagikan ke WhatsApp
  • Screenshotbot menggunakan status RAM proses server web sebagai penyimpanan data tanpa DB terpisah, lalu memulihkan status setelah gangguan dengan snapshot dan log transaksi
  • Dengan mengurangi serialisasi SQL, bolak-balik ke DB, dan layanan pekerjaan latar belakang terpisah, pendekatan ini menyederhanakan pengalaman pengembangan proses tunggal serta memanfaatkan indeks in-memory dan pemrosesan berbasis thread
  • Ketersediaan tinggi dicapai dengan mereplikasi log transaksi menggunakan algoritme konsensus Raft ke tiga server, sehingga saat pemimpin gagal, pemimpin baru mengambil alih permintaan dalam beberapa detik
  • Implementasi nyatanya menggabungkan Common Lisp, bknr.datastore, bknr.cluster open source, Baidu Braft, dan EFS, dengan restart server biasanya hanya terjadi sekali tiap 1–2 bulan
  • Bahkan ketika CI pelanggan enterprise ternama memanggil API ratusan kali untuk setiap commit dan Pull Request, penggunaan CPU pada mesin 4-core 16GB tetap maksimal sekitar 20%, dan sebagian besar berasal dari pemrosesan gambar

Struktur yang memperlakukan status RAM seperti database

  • Layanan web tradisional umumnya memilih kombinasi framework web seperti Rails, Django, atau Node bersama database seperti MySQL, PostgreSQL, atau MongoDB
  • Dalam 10 tahun terakhir, muncul perubahan lingkungan yang membuat pendekatan ini layak ditinjau ulang
    • Disk menjadi lebih cepat berkat NVMe
    • Disk seperti EBS/EFS menjadi lebih andal
    • RAM menjadi murah sehingga sebagian besar data startup bisa muat di RAM
    • Kini bisa menyewa mesin dengan ratusan core
    • Pada 2014, algoritme konsensus Raft diperkenalkan dan implementasi yang tangguh semakin banyak
  • Arsitektur ini menggabungkan layanan web dan instance database, lalu memakai status memori proses sebagai database
  • Alih-alih menyimpan data dengan serialisasi seperti SQLite, objek dan field di dalam RAM diperlakukan langsung sebagai status aplikasi

Explore: cara menyederhanakan iterasi produk awal

  • Jika semua data ada di RAM, tidak perlu serialisasi ke query SQL, dan struktur banyak server frontend yang terhubung ke satu DB juga bisa dikurangi
  • Saat beban meningkat, hal ini bisa ditangani dengan memakai server yang lebih besar dengan RAM dan CPU lebih banyak
  • Indeks dapat menggunakan struktur seperti hash table in-memory alih-alih B-tree yang disesuaikan untuk latensi disk
    • Di Screenshotbot, indeks yang menggunakan functional collections penting untuk skalabilitas
  • Karena pembacaan data hanyalah pembacaan RAM, tidak diperlukan struktur khusus atau Async-IO untuk mengurangi bolak-balik ke DB
  • Pekerjaan latar belakang menjadi thread yang berjalan di dalam proses besar yang sama, dan penanganan konkurensi sebagian besar bisa diselesaikan dengan mutex in-memory dan condition variable

Pemulihan gangguan: snapshot dan log transaksi

  • Untuk menghadapi crash proses, seluruh status RAM disimpan secara berkala sebagai snapshot
  • Perubahan setelah snapshot terakhir terlebih dahulu dicatat ke disk sebagai log transaksi, lalu status memori diubah
    • foo.setBar(2) mencatat transaksi bahwa field bar milik foo berubah menjadi 2, lalu baru mengubah field sebenarnya
    • new Foo() mencatat transaksi bahwa objek Foo dibuat, lalu mengembalikan objek baru
  • Saat restart, sistem terlebih dahulu membaca snapshot lalu memutar ulang log transaksi untuk memulihkan status
  • Perubahan indeks tidak perlu dimasukkan ke log transaksi
    • Misalnya, jika ada indeks pada field bar milik Foo, maka setBar akan memperbarui indeks tersebut, dan pembaruan ini juga akan terjadi lagi saat snapshot dimuat atau transaksi diputar ulang

Bentuk kode yang dimungkinkan oleh proses tunggal

  • Karena semua permintaan diproses dalam proses yang sama, closure dapat disimpan di memori server dan digunakan untuk menangani permintaan halaman
  • URL Screenshotbot berbentuk https://screenshotbot.io/n/nnnnnnn dipetakan ke closure internal
  • Karena closure menyimpan referensi objek, kebutuhan untuk meneruskan ID objek atau menserialisasi objek setiap kali pindah halaman jadi berkurang
  • Target debugging, profiling, dan monitoring juga menyempit menjadi satu layanan
    • Tidak ada lagi titik observasi DB terpisah seperti MySQL slow query log
    • Jika satu layanan ini mati maka situs juga mati, tetapi bila hanya ada satu layanan dan satu server, mereka menganggap kemungkinan kegagalannya juga lebih rendah
    • Jika server mati, AWS dapat menyalakan server baru dalam beberapa menit
  • Kode pengujian juga menjadi lebih mudah karena tidak perlu melakukan mock pada database

Expand: memastikan ketersediaan tinggi dengan Raft

  • Jika pelanggan berisiko tinggi menuntut ketersediaan 99.999%, struktur server tunggal saja tidak cukup
    • Saat server gagal, AWS bisa memerlukan beberapa menit untuk menyalakannya kembali
    • Proses memulihkan snapshot dari disk juga bisa memakan beberapa menit
    • Restart layanan saat redeploy dapat membuat server tidak aktif selama beberapa menit
  • Algoritme konsensus Raft mereplikasi log transaksi dari server web/database yang merupakan finite state machine
  • Jika direplikasi ke 3 mesin, saat pemimpin gagal, pemimpin baru akan terpilih dalam beberapa detik dan terus memproses permintaan
  • Tanpa banyak mengubah cara developer menulis kode, layanan sederhana dapat dijadikan seperti database dengan ketersediaan tinggi
  • Dalam konfigurasi berbasis Raft, rolling deployment juga dimungkinkan tanpa mematikan server

Extract: sharding dan bottleneck yang diperkirakan

  • Saat masuk tahap menangani lebih banyak pelanggan besar, sharding bisa diterapkan seperti cara perusahaan besar mengelola database
  • Setiap shard bisa menjadi klusternya sendiri
  • Screenshotbot sudah menyediakan kluster khusus per pelanggan enterprise
  • Meta telah beralih ke Raft untuk menangani replikasi kluster MySQL, dan Screenshotbot memakai pendekatan serupa tanpa database terpisah
  • Kandidat bottleneck utama adalah skalabilitas commit-thread
    • Thread baca bisa diparalelkan dengan baik
    • Satu commit-thread menerapkan transaksi satu per satu
    • Karena Raft meng-commit beberapa transaksi ke disk sekaligus, latensi disk tidak terlalu penting
    • Titik kekhawatirannya adalah jika biaya CPU untuk menerapkan transaksi melebihi performa satu core
    • Dalam kasus itu, biaya commit dapat diprofilkan lalu sebagian pekerjaan dipindahkan ke luar thread transaksi atau dipertimbangkan sharding

Stack nyata Screenshotbot

  • Screenshotbot menggunakan Common Lisp
  • Implementasi awal memakai MySQL, tetapi karena sulit menangani konkurensi dengan MySQL, mereka menggantinya dengan bknr.datastore
  • bknr.datastore adalah library yang menyediakan struktur yang dijelaskan pada tahap Explore untuk Common Lisp
  • Dalam struktur ini, thread di dalam satu proses menangani permintaan web, sehingga multithreading yang kuat menjadi penting
    • Karena kebutuhan ini, Ruby atau Python dianggap kurang cocok
  • Karena closure dipertahankan di memori server, server sulit direstart terlalu sering
    • Jika direstart, closure akan hilang
    • Sebagai gantinya, kode diperbarui lewat hot reloading pada proses yang sedang berjalan
    • Common Lisp menyediakan fitur seperti reinitialize-instance, standar untuk memperbarui objek yang sudah ada saat definisi kelas berubah

Kluster, penyimpanan file, dan skala operasi

  • Restart server saat ini biasanya hanya terjadi sekitar sekali tiap 1–2 bulan
  • Saat restart diperlukan, mereka melakukan rolling restart di kluster Raft
  • Setiap instalasi memakai kluster 3 server, dan konfigurasi ini memungkinkan 1 server gagal
  • Saat ini mereka tidak memakai Kubernetes dan merasa belum membutuhkannya
  • Implementasi Raft adalah library buatan sendiri di atas bknr.datastore
    • bknr.cluster telah dirilis sebagai open source
    • Secara internal, ia menggunakan Braft dari Baidu
    • Braft menangani snapshot di latar belakang, sehingga server tetap bisa memproses permintaan saat snapshot dibuat
  • File gambar atau blob yang tidak seharusnya masuk ke datastore disimpan di EFS yang dibagikan oleh tiga server
    • EFS adalah NFS dengan ketersediaan tinggi
    • Mereka menganggapnya lebih mudah dipakai daripada S3 karena tidak perlu menangani kondisi error terpisah
    • Karena menulis langsung ke disk tanpa berinteraksi dengan server eksternal, pengujiannya juga dianggap lebih mudah

Kinerja saat ini dan cakupan penerapan

  • Screenshotbot mendukung beberapa pelanggan enterprise besar dan satu pelanggan yang sangat terkenal
  • Sistem ini berjalan di CI pelanggan tersebut dan menerima ratusan permintaan API untuk setiap commit dan Pull Request
  • Bahkan dengan beban ini, pemrosesan permintaan cukup dijalankan di mesin 4-core 16GB
    • Server replikasi juga memakai mesin serupa dan sebagian besar menganggur
    • Penggunaan CPU maksimal sekitar 20%
    • Sebagian besar penggunaan CPU berasal dari pemrosesan gambar
  • Penting untuk tidak merancang sistem dengan asumsi skala yang lebih besar dari yang sebenarnya dibutuhkan
  • Jika memilih Common Lisp, konfigurasi terkait tersedia melalui Screenshotbot OSS

1 komentar

 
GN⁺ 2024-08-11
Opini Hacker News
  • Arsitektur ini kurang lebih mirip dengan cara HashiCorp membuat Nomad, Consul, dan Vault (saya salah satu maintainer Nomad). Memang jelas arsitektur yang tidak biasa, tetapi setelah terbiasa, pengalaman developernya cukup baik
    State di dalam memori bisa dibentuk sesuai keinginan, sehingga kita bisa membuat sendiri fungsi pengindeksan dan kueri yang disesuaikan dengan aplikasi. Untuk Raft FSM, Anda juga bisa memakai SQLite :memory:, tetapi jika bisa membuat atau menemukan penyimpanan transaksional di dalam memori (kami memakai go-memdb buatan sendiri), membaca state hanya menjadi pemanggilan fungsi. Mencegah stale read atau bias tulis juga sederhana. Karena setiap objek yang ditulis memiliki indeks Raft, kita bisa membuat API seperti “kueri objek foo ke follower, tetapi tunggu setidaknya sampai indeks 123”. Ini menghilangkan banyak “keajaiban” yang biasanya kita dorong ke RDBMS atau penyimpanan eksternal
    Namun saya akan berhati-hati memilih arsitektur seperti ini untuk startup baru di luar ranah “infrastruktur”. Sebab pada dasarnya Anda sedang membuat database sendiri. Anda harus memilih dengan baik atau menulis sendiri komponen dasar seperti RPC antar-node, persistensi disk, dan penyimpanan state transaksional di dalam memori. Upgrade khususnya sulit; kode baru bisa saja mencoba menulis entitas ke log Raft yang tidak dipahami node versi lama. Lebih buruk lagi, cara pemrosesannya bisa berubah sehingga node lama salah memahaminya. Tidak ada makan siang gratis

    • Bagian “untuk Raft FSM, Anda juga bisa memakai SQLite :memory:” adalah desain dasar yang digunakan rqlite[1] selama kira-kira 7 tahun pertama. Namun rqlite pindah ke SQLite berbasis disk, dan dengan mode WAL serta PRAGMA synchronous=OFF[2], kecepatannya sama cepatnya dengan menulis ke RAM atau cukup mendekati. Berkat itu, rqlite juga bisa menghindari keterbatasan database SQLite :memory:, salah satunya batas ukuran maksimum 2GB. Seharusnya sejak awal kami memakai mode disk, tetapi baru sekarang menyadarinya
      Karena rqlite memakai library Raft[3] yang sama dengan Nomad, mungkin sebagian dari hal ini sudah Anda ketahui
      Masalah upgrade memang nyata. Saya penasaran apakah di Nomad hal ini sering ditemui di lapangan. Selama 10 tahun pengembangan rqlite, sangat jarang kami memperkenalkan tipe Raft Entry baru, dan hanya satu kali pengguna nyata menghadapinya. Salah satu cara menanganinya adalah dengan terlebih dahulu merilis versi yang memahami tipe baru tetapi sama sekali tidak menulisnya, lalu setelah versi itu terpasang sepenuhnya, baru naik ke versi yang benar-benar memakai tipe baru. Namun kami belum pernah benar-benar melakukannya, dan itu juga menuntut disiplin dari pengguna akhir
      [1] https://www.rqlite.io
      [2] Ini mungkin terdengar berbahaya, tetapi dalam desain rqlite saat ini, saat startup database SQLite utama direkonstruksi sepenuhnya dari log Raft (log Raft di-fsync pada setiap penulisan). Jadi meskipun database SQLite rusak karena pemadaman listrik dan sebagainya, itu tidak terlalu berarti karena database SQLite bukan penyimpanan data otoritatif rqlite
      [3] https://github.com/hashicorp/raft
    • Dibandingkan balasan lain di sini, saya juga lebih terbuka terhadap gagasan menyimpan data di memori. Saat membaca bagian tulisan yang menyebut Common Lisp dan hot reloading, saya berpikir, “Kalau tim itu, mungkin mereka boleh melakukan apa pun sesukanya. Tapi tidak semua orang bekerja di tim itu”
    • Pernyataan bahwa “upgrade khususnya sulit” memang benar. Namun itu tidak berlaku untuk startup pada tahap Explore yang belum membutuhkan replikasi, dan kami juga lama berada di posisi seperti itu. Justru pada tahap inilah arsitektur ini paling berguna untuk iterasi produk
      Namun ketika mulai memakai replikasi pada tahap Expand, memang muncul tantangan engineering. Meski begitu, semuanya adalah masalah yang bisa diselesaikan. Di Common Lisp, kode bisa di-hot reload, sehingga beberapa migrasi menjadi jauh lebih mudah, dan itu juga membantu
  • Puluhan tahun lalu, PG menulis bahwa di Viaweb ia tidak menggunakan database, dan bahwa rasanya aneh aplikasi web menjadi seperti frontend untuk database, padahal aplikasi desktop tidak begitu[0]. HN juga tidak menggunakan database
    Namun karena aplikasi desktop dan mobile modern kini sering menggunakan database, biasanya SQLite, pernyataan itu tidak lagi sepenuhnya tepat. Sebab ternyata penyimpanan dan kueri data relasional cukup berguna di rentang aplikasi yang sangat luas
    [0] https://www.paulgraham.com/vwfaq.html

    • Setelah membaca tautannya, sepertinya “database” tidak berarti hal yang sama bagi semua orang
      Di vwfaq masih ada bagian yang menyebut membaca data dari disk, dan juga ada kalimat “memulai proses untuk merespons permintaan HTTP”. Di sini, “database” tampaknya berarti server terpisah untuk mempersistenkan data, serta arsitektur yang harus berkomunikasi dengan server lain untuk mengambil data tersebut
      Dengan definisi ini, tentu saja SQLite tidak termasuk database. Selain itu, jika sudah membaca data dari disk, berarti Anda sedang menggunakan database, atau mengimplementasikan lapisan persistensi buatan sendiri yang bersifat sementara. Pertanyaannya adalah apakah membaca data dari SQLite saat aplikasi mulai tetap dianggap menggunakan database
      Masalah dengan cara berpikir seperti ini adalah ia mengabaikan fakta bahwa inti database adalah menyimpan dan mengambil data dengan cara yang nyaman tanpa perlu memikirkan detail tingkat rendah. Menyimpan data di database bukan berarti menjalankan instance Postgres di suatu tempat lalu mengambil data lewat web. Jika Anda menaruh semua data di memori, lalu memiliki proses yang menyimpan snapshot ke disk dengan struktur data berbasis log, selamat. Anda baru saja membuat database sendiri
    • Jelas bahwa kami dipengaruhi oleh tulisan PG. Kami juga memakai Common Lisp, dan sulit menghindari PG di bidang ini. Namun sepertinya Viaweb tidak menggunakan log transaksi seperti bknr.datastore, dan hal itu membuat proses pengembangan jauh lebih mulus
    • Saat PG menulis Viaweb, SQLite sendiri belum seumum sekarang. Koreksi: saat itu SQLite bahkan belum ada. Jika tidak ada SQLite dan opsinya praktis hanya key-value store, dalam kebanyakan kasus filesystem pun mungkin sudah cukup
      Kedua, selama 20 tahun terakhir, kueri RDBMS menjadi jauh lebih sederhana. Muncul berbagai ORM dan row mapper yang mengurangi kode berulang
      Fitur lanjutan seperti full-text search yang berguna untuk aplikasi desktop dan mobile juga muncul. Saat ini, memakai RDBMS untuk aplikasi desktop adalah pilihan yang bagus
    • HN tidak menggunakan database? Bisa jelaskan lebih lanjut? Cukup mengejutkan
    • Saat itu zamannya berbeda. Setahu saya, Viaweb terdiri dari beberapa instance Common Lisp, dan seluruh state sesi pengguna berada di memori masing-masing mesin. Saya ingat pernah membaca di suatu tempat bahwa mereka menambal bug secara real-time sambil berbicara dengan pengguna di production
      Web sudah jauh lebih besar, dan banyak praktik seperti ini tidak akan berjalan hari ini. Jika seseorang mendorong perbaikan live ke mesin production sambil menelepon pelanggan, dengan beban pengujian seperti sekarang, banyak orang di sini mungkin akan mempertanyakan kondisi mental saya
  • Saya paham keinginan untuk bereksperimen dengan sesuatu yang menarik, tetapi melakukan ini demi menghindari mempelajari bagian paling dasar dari MySQL atau Postgres terlihat seperti pemborosan waktu yang luar biasa. Tinggal bangun saja di atasnya, terutama jika menjalankannya di public cloud
    Argumen tentang peningkatan latensi round-trip atau masalah konkurensi tidak meyakinkan. Untuk yang terakhir, ada solusi sederhana seperti tuning dasar atau memisahkan pelanggan yang berisik. Di tulisan lain di blog mereka, mereka membahas kemungkinan menambahkan 10 juta baris per hari dan tantangan indexing, tetapi itu secara harfiah bukan apa-apa. Bahkan jika 10 kali lipat pun, menurut saya itu belum menjadi alasan untuk merekayasa solusi kustom
    Sampai benar-benar dibutuhkan, “yang buruk lebih baik” adalah pendekatan yang tepat, dan ketika saatnya tiba Anda akan mengetahuinya dengan jelas. Pada titik itu Anda juga akan tahu bottleneck-nya, sehingga bisa merespons dengan lebih bijak daripada membuat semuanya berlebihan sejak awal

    • Untuk engine database berbasis server, argumen mengurangi panggilan jaringan masih bisa diajukan. Memang meragukan, tetapi masih mungkin
      Namun membingungkan ketika si blogger berargumen bahwa alasan tidak memilih SQLite adalah karena mungkin ada fitur yang tidak diperlukan. Itu konyol dan tidak membenarkan apa pun
      Tulisan itu terbaca seperti berangkat dari solusi buruk untuk masalah hipotetis, lalu melakukan upaya putus asa dengan rangkaian argumen yang dipaksakan demi menolak solusi yang jelas
    • Yang membuat saya penasaran adalah apakah bisnis mereka akan berhasil jika mereka tidak menghabiskan waktu untuk menciptakan ulang roda. Membangun secara terbuka dan menulis blog saja sudah mempromosikan produk dan menunjukkan kemampuan teknis. Kalau mereka memakai teknologi membosankan yang berjalan baik saat digabungkan, apakah bahan cerita akan berkurang, sehingga efek promosinya juga lebih kecil?
      Saya bertanya-tanya apakah pemikiran saya keliru, atau justru upaya tambahan yang kontroversial tetapi tampak tidak perlu ini merupakan bagian dari produk dan cara untuk berhasil di ruang ini
  • Aneh rasanya tulisan ini dimulai dengan “Saya tidak sedang membicarakan sesuatu seperti SQLite, yang datanya tetap diserialisasi”, tetapi akhirnya berujung pada log transaksi buatan sendiri yang tetap membutuhkan serialisasi dan replikasi. Replikasi basis data memang pada dasarnya dilakukan seperti itu
    Kalau seluruh beban masuk ke satu server, jalankan saja basis data di server itu, dan lupakan “arsitektur khusus untuk mengurangi round-trip ke basis data”. Kalau seluruh data muat di RAM, gunakan ramdisk untuk basis data kalau mau, lalu replikasi ke penyimpanan permanen dengan alat standar. Itu justru benar-benar sederhana

    • Secara garis besar, rasanya bisa diringkas sebagai “membuat SQLite + replikasi Raft sendiri”. Hanya saja tanpa keandalan SQLite yang sudah teruji, atau kemampuannya memindahkan data dari memori ke disk secara efisien
      Jadi pada dasarnya mirip https://litestream.io/. Berkat konfigurasi Raft yang eksplisit, failover mungkin bisa lebih cepat. Saya bukan pengguna Litestream, jadi tidak tahu perbedaan halusnya, tetapi kedengarannya sangat mirip
      Terlepas dari penyederhanaan berlebihan seperti ini, idenya sendiri cukup saya sukai, dan menurut saya tulisannya juga cukup meyakinkan dalam menjelaskan konsepnya. Untuk banyak sistem, bahkan jika suksesnya tidak wajar, ini akan cukup berskala untuk menanggung sebagian besar atau seluruh bisnis, dan performanya akan luar biasa bagus dibandingkan hampir semua alternatif
    • Menurut saya ramdisk juga tidak perlu. Basis data sudah mencache semuanya di memori, dan hanya penulisan yang sampai ke disk
      Cukup lakukan cold start pada basis data lalu jalankan select yang cukup besar dua kali
    • Penting untuk memahami bahwa semua startup melewati tiga tahap: Explore, Expand, Extract. Sesuatu yang sederhana di satu tahap belum tentu sederhana di tahap lain
      Basis data transaksional sederhana pada tahap Expand dan Extract, tetapi pada tahap Explore ia menjadi beban tambahan karena membuat kita fokus pada masalah infrastruktur, bukan produk. Pada tahap Explore belum ada pelanggan, jadi belum ada data, dan keandalan data juga belum penting
      Pendekatan bknr.datastore yang menaruh semuanya di memori (tanpa replikasi) sederhana pada tahap Explore. Namun begitu masuk tahap Expand, muncul beban operasional untuk menjamin konsistensi data
      Tetapi pada saat mencapai tahap Expand, produk sudah tervalidasi dan banyak kode sudah ditulis. Menulis ulang semuanya ke basis data transaksional tidak masuk akal, dan menambahkan replikasi Raft di atasnya lebih mudah
    • Setuju. Membuat ulang WAL berarti juga membuat ulang, atau mengabaikan, semua kerepotan yang menyertainya. Sepertinya pemulihan dari log memakan waktu cukup lama, jadi mungkin mereka bahkan belum benar-benar sampai ke checkpointing log
    • Sistem trading secara terang-terangan menaruh semuanya di struktur yang sudah dialokasikan sebelumnya di RAM. Ini tergantung kompromi mana yang dipilih
  • Logika tulisan ini membingungkan. Apakah ini maksudnya cara untuk membuat aplikasi yang stateful menjadi lebih sederhana dan cepat?
    Premisnya lemah dan klaimnya berlebihan. Penulis melebih-lebihkan kesulitan serialisasi agar argumen yang lemah terlihat lebih kuat

    • Dari tulisan blognya sangat terasa nuansa “lihat betapa pintarnya kami”
      Orang seperti ini biasanya sulit diajak bekerja sama. Syukurlah mereka menemukan startup untuk ditenggelamkan, jadi saya tidak perlu berurusan dengan mereka
    • Lalu mereka mengimplementasikan serialisasi untuk menulis transaksi ke log dan mereplikasikannya ke node lain
  • Saat memulai proyek baru, struktur datanya biasanya berupa “daftar item dengan atribut”. Misalnya, sekarang saya sedang menulis aplikasi fitness; datanya adalah daftar latihan, dan tiap latihan memiliki judul, deskripsi, URL video, serta atribut lain
    Biasanya saya mulai dengan menaruh item-item itu di file YAML dalam direktori data. Sebenarnya itu dialek YAML kustom yang menghilangkan keanehan YAML asli. Setiap nilai adalah string, tanpa konversi tipe yang ajaib. Membuat item baru hanyalah menjalankan vim crunches.yaml lalu memasukkan data, dan mengedit serta menghapus juga sangat mudah dalam struktur data ini
    Ketika proyek membesar, biasanya saya membuat skema DB dan memindahkan item-item itu ke MariaDB atau SQLite
    Kali ini saya berencana memindahkan item (latihan) ke kolom JSON di DB SQLite. Semua atribut satu item akan disimpan dalam satu field JSON, lalu saya akan menulis penjelajah DB kecil yang memungkinkan field JSON diedit seperti YAML. Tujuannya mempertahankan kenyamanan mengedit data yang bisa dibaca manusia
    Menulis penjelajah DB sepertinya cukup langsung. Dengan sedikit ncurses, menelusuri tabel, memilih satu, menelusuri baris, menyisipkan dan menghapus baris. Saat mengedit field, Vim dibuka. Jika field berupa JSON, ubah dulu menjadi YAML sebelum dikirim ke Vim, lalu ketika pengguna keluar dari Vim, ubah kembali menjadi JSON

  • Bagian awal tulisan pada dasarnya mirip dengan cara kerja mesin NUMA (misalnya SGI Altix atau UV). Keunggulan yang mereka klaim juga berupa latensi rendah dan kemampuan memparalelkan pekerjaan dengan multithreading di RAM besar. Clustering muncul sebagai alternatif murah untuk mesin seharga lebih dari 1 juta dolar. Ada juga kemiripan dengan persistensi AS/400, ketika aplikasi cukup menulis ke memori dan secara transparan dipetakan ke disk
    Kini, dengan hardware murah, kita seolah mundur ke masa lalu menuju keunggulan mesin NUMA terklaster. Dalam prosesnya ada juga peningkatan, dan tulisannya menarik dibaca
    Teknik lain di masa lalu adalah menghapus stack TCP/IP di dalam klaster untuk menghilangkan masalah terkait. Solusi seperti Active Messages adalah lapisan tipis di atas hardware. Ada juga desain router jaringan dengan konsistensi kuat bawaan. Ada cukup banyak hal yang bisa mereka lakukan
    Jika membesar, ada juga peluang hardware. Di sisi CPU, SGI melakukan dua hal. Mesin NUMA memperbesar jumlah CPU dan RAM dalam satu sistem, dan FPGA ditancapkan langsung ke bus memori agar bisa digunakan sebagai akselerator kustom. Terakhir, beberapa makalah ilmu komputer memodifikasi instruction set prosesor, jaringan internal chip, dan sebagainya untuk menghilangkan atau mengurangi bottleneck multithreading. Chip seperti OpenPiton meningkatkan jumlah core dengan core yang terbuka dan dapat dikustomisasi (misalnya 32 buah)

  • “Bayangkan betapa kerennya hal-hal yang bisa kita bangun jika tidak perlu menserialisasi data menjadi kueri SQL” sebenarnya sudah ada dalam implementasi model aktor[0] yang cukup matang, misalnya Akka Event Sourcing[1]. Ini juga menangani masalah berikut
    “Namun bagian pentingnya adalah bagaimana memulihkan diri ketika proses crash. Jawabannya mudah. Ambil snapshot seluruh RAM secara berkala”
    Ini pada dasarnya sudah terselesaikan tanpa perlu membuat “arsitektur baru untuk pengembangan web”. Ada juga upaya open source untuk mengeksplorasi protokol RAFT menggunakan aktor di sini[2] dan di sini[3]
    0 - https://en.wikipedia.org/wiki/History_of_the_Actor_model
    1 - https://doc.akka.io/docs/akka/current/typed/persistence.html
    2 - https://github.com/Michael-Dratch/RAFT_Implementation
    3 - https://github.com/invkrh/akka-raft

  • Pikiran pertama saya adalah, “Ah, ini cara yang dulu saya pakai saat menulis dengan Common Lisp; menarik juga ada yang menemukan kembali teknik itu”
    Tapi ternyata bukan begitu; hanya saja ada lebih banyak orang Lisp

  • “RAM sangat murah” mungkin salah satu kesalahpahaman terbesar para developer
    SSD telah meningkat 100–10000 kali lipat dari sisi throughput atau IOPS, dan performa vCPU per dolar juga naik 20–50 kali. Dari 45/32nm kini kita sudah sampai 5nm/3nm, dan jumlah instruksi per clock juga jauh lebih tinggi
    Namun harga RAM hampir tidak turun sebesar CPU atau SSD. Bisa jadi RAM jauh lebih cepat, kita bisa memasang lebih banyak memori dengan chip berdensitas lebih tinggi, dan channel mungkin sudah bertambah dari dual menjadi 8 atau 12. Tetapi jika melihat harga spot DRAM 2008–2022, harga DRAM terendah tiga kali berada di level yang sama, sekitar 2,8 dolar/GB. Dalam periode yang sama, sesuai siklus, harganya naik-turun sampai 6–8 dolar/GB. Artinya, jika membeli DRAM pada titik terendah atau tertinggi selama sekitar 15 tahun terakhir, dengan mengabaikan inflasi, harganya kira-kira mirip di kisaran ±10–20%
    Baru pada pertengahan 2022 batas 2,8 dolar/GB itu ditembus dan harga jatuh mendekati 1 dolar/GB, lalu menetap di sekitar 2 dolar/GB untuk DDR5
    Sekarang memang kita bisa memasang RAM 4TB dalam satu server. Tapi itu bukan berarti DRAM sangat murah. Developer rata-rata atau developer big tech sekarang menghasilkan jauh lebih banyak dibanding 2010, sehingga RAM terasa jauh lebih terjangkau. Kenyataannya, bahkan pada titik terendah dalam 15 tahun terakhir, penurunan harga DRAM paling banter hanya sedikit di atas 2 kali lipat. Dan besar kemungkinan harga DRAM akan melonjak lagi dalam 1–2 tahun

    • Ada interpretasi lain yang juga mungkin. Kapasitas RAM maksimum per node telah meningkat drastis selama beberapa dekade terakhir
      Sebagai contoh sederhana, jika 20 tahun lalu sebuah node tertentu dibatasi pada RAM 16GB, maka untuk mendapatkan RAM 4TB dalam sebuah sistem dibutuhkan 256 node (di luar overhead masing-masing OS)
      Saat ini satu node bisa menampung seluruh 4TB itu dalam satu sasis
      Total biaya chip RAM itu sendiri mungkin tidak berubah, tetapi biaya untuk benar-benar menggunakan RAM tersebut dalam sistem fisik telah turun secara dramatis
    • Pada saat yang sama, banyak developer terlalu cepat beralih ke sistem terdistribusi padahal cukup membeli RAM lebih banyak. Mungkin itu juga yang dimaksud penulis
    • Terima kasih untuk datanya. Saya setuju dengan balasan lain. Sepertinya yang seharusnya saya katakan bukan “murah”, melainkan mesin dengan RAM ratusan GB kini lebih mudah didapat