IsleDB / Docs / Reader service

Reader service

isledb reader is a service that serves reads of one IsleDB database over HTTP. Run as many replicas as you need behind a load balancer: they share nothing, so each one adds capacity. The HTTP API is described in the reader HTTP API.

Start a reader

With a configuration file:

isledb reader --config /etc/isledb/isledb.yaml

Or with flags:

isledb reader \
  --bucket-url 's3://my-bucket?region=us-east-1' \
  --prefix prod/accounts \
  --cache-dir /var/cache/isledb \
  --auth-token-file /etc/isledb/tokens

The reader reads storage credentials from the usual places for your cloud provider, like the writer. Credentials never go in its configuration.

Readers and the writer can start in any order. Until the database is first written, a reader answers every key with 404 at revision 0, and it picks up the data at its next refresh after the first write.

Freshness and cost

A reader loads the database's newest data every views.refresh_after, 1 second by default, so reads are about that far behind the writer. Each load reads at least one small object from storage: about 86,400 reads a day per replica, more when the database changes.

With an isledb cache in the same region (read_cache.url), replicas read through it instead: they usually load new data within a second of each write, and storage sees reads from the cache rather than from every replica.

If the database has a change feed, every replica also serves it at /v1/changes; see Follow changes. The feed's newest position comes from the same loads as the data, and new changes show at the same time as new data. Consumers that have caught up are answered from memory: polling costs about one read per new position per replica, however many consumers poll. A change feed turned on later shows at the next load.

Configuration

You can set each option in a YAML file, as an environment variable, or as a flag. Flags take priority over environment variables, which take priority over the file.

A typical configuration:

bucket_url: s3://my-bucket?region=us-east-1
log_level: info

reader:
  listen: :8080
  admin_listen: 127.0.0.1:8081

  prefix: prod/accounts
  cache_dir: /var/cache/isledb

  read_cache:
    url: https://isledb-cache:8090
    token_file: /etc/isledb/cache-token
    ca_file: /etc/isledb/tls/cache-ca.pem   # only for a cache with a private CA

  auth:
    token_file: /etc/isledb/tokens

Every option of the reader section, at its default where it has one:

reader:
  listen: :8080
  admin_listen: 127.0.0.1:8081
  shutdown_drain: 5s

  prefix: prod/accounts          # required
  cache_dir: /var/cache/isledb   # required, one per replica

  caches:
    disk_bytes: 8GiB
    block_bytes: 256MiB
    bloom_bytes: 64MiB
  views:
    refresh_after: 1s
  reads:
    max_concurrent: 256

  read_cache:
    url: https://isledb-cache:8090
    token_file: /etc/isledb/cache-token
    ca_file: /etc/isledb/tls/cache-ca.pem    # only for a cache with a private CA
    cert: /etc/isledb/tls/reader.pem         # only for a cache that requires
    key: /etc/isledb/tls/reader-key.pem      # client certificates

  auth:
    token_file: /etc/isledb/tokens
    # insecure: true                         # development only
  tls:
    # cert: /etc/isledb/tls/server.pem       # serve HTTPS
    # key: /etc/isledb/tls/server-key.pem
    # client_ca: /etc/isledb/tls/clients.pem # require client certificates

To check a configuration without starting the reader:

isledb reader --config isledb.yaml --check

It checks the settings and prints the configuration they resolve to. It doesn't open the token, CA or certificate files: a missing one stops the reader when it starts.

Every setting, with its flag, environment variable and default, is in the configuration reference. Authentication and TLS work as for every service: see Secure IsleDB.

The caches can't be turned off: each size must be positive.

After setting read_cache.url, check that it works. A reader that can't use the cache, because of a wrong URL, a wrong token, or a cache using TLS with a certificate the reader doesn't trust, still answers every read, from storage. Watch isledb_reader_read_cache_fallbacks_total: if it rises with every read, the cache isn't being used. A missing or unreadable ca_file, cert or key is different: the reader refuses to start.

Memory

Plan for the block and Bloom caches (about 320 MiB by default), plus the values being served: up to reads.max_concurrent values, or scan pages of about 1 MiB plus one value, at once. With large values, lower reads.max_concurrent or raise the memory limit.

Health checks

Served on admin_listen, without authentication.

Path Answers
/healthz 200 while the process is running.
/readyz 200 while the reader has data to serve. 503 while starting, while shutting down, or after it has lost access to storage for longer than the database's max_pinned_view_age (1 hour by default), when its data expires. Until then a reader that can't refresh stays ready and serves older data: see the falling-behind alert below.
/metrics Prometheus metrics.
/debug/pprof/ Go profiling.

Metrics

The reader's metrics, and what to alert on, are in the metrics reference. Above all, alert when the data a reader serves gets older than you accept: time() - isledb_reader_view_loaded_timestamp_seconds grows whenever loading new data fails. The reader keeps serving what it has, and stays ready, until that data is max_pinned_view_age old; taking every replica out of service at once would turn old reads into no reads.

Shutting down

On SIGTERM or SIGINT, the reader reports itself not ready, waits shutdown_drain, finishes reads in progress, and exits. It holds nothing that needs saving: its disk cache is only a cache.