Categorygithub.com/localrivet/galaxycache
modulepackage
0.0.0-20211211122255-60f325a24b5a
Repository: https://github.com/localrivet/galaxycache.git
Documentation: pkg.go.dev

# README

galaxycache

Build Status

galaxycache is a caching and cache-filling library, adapted from groupcache, intended as a replacement for memcached in many cases.

For API docs and examples, see http://godoc.org/github.com/localrivet/galaxycache

Quick Start

Initializing a peer

// Generate the protocol for this peer to Fetch from others with (package includes HTTP and gRPC)
grpcProto := NewGRPCFetchProtocol(grpc.WithInsecure())

// HTTP protocol as an alternative (passing the nil argument ensures use of the default basepath
// and opencensus Transport as an http.RoundTripper)
httpProto := NewHTTPFetchProtocol(nil)

// Create a new Universe with the chosen peer connection protocol and the URL of this process
u := NewUniverse(grpcProto, "my-url")

// Set the Universe's list of peer addresses for the distributed cache
u.Set("peer1-url", "peer2-url", "peer3-url")

// Define a BackendGetter (here as a function) for retrieving data
getter := GetterFunc(func(ctx context.Context, key string, dest Codec) error {
   // Define your method for retrieving non-cached data here, i.e. from a database
})

// Create a new Galaxy within the Universe with a name, the max capacity of cache space you would
// like to allocate, and your BackendGetter
g := u.NewGalaxy("galaxy-1", 1 << 20, getter)

// In order to receive Fetch requests from peers over HTTP or gRPC, we must register this universe
// to handle those requests

// gRPC Server registration (note: you must create the server with an ocgrpc.ServerHandler for
// opencensus metrics to propogate properly)
grpcServer := grpc.NewServer(grpc.StatsHandler(&ocgrpc.ServerHandler{}))
RegisterGRPCServer(u, grpcServer)

// HTTP Handler registration (passing nil for the second argument will ensure use of the default 
// basepath, passing nil for the third argument will ensure use of the DefaultServeMux wrapped 
// by opencensus)
RegisterHTTPHandler(u, nil, nil)

// Refer to the http/grpc godocs for information on how to serve using the registered HTTP handler
// or gRPC server, respectively:
// HTTP: https://golang.org/pkg/net/http/#Handler
// gRPC: https://godoc.org/google.golang.org/grpc#Server

Getting a value

// Create a Codec for unmarshaling data into your format of choice - the package includes 
// implementations for []byte and string formats, and the protocodec subpackage includes the 
// protobuf adapter
sCodec := StringCodec{}

// Call Get on the Galaxy to retrieve data and unmarshal it into your Codec
ctx := context.Background()
err := g.Get(ctx, "my-key", &sCodec)
if err != nil {
   // handle if Get returns an error
}

// Shutdown all open connections between peers before killing the process
u.Shutdown()

Concepts and Glossary

Consistent hash determines authority

A consistent hashing algorithm determines the sharding of keys across peers in galaxycache. Further reading can be found here and here.

Universe

To keep galaxycache instances non-global (i.e. for multithreaded testing), a Universe object contains all of the moving parts of the cache, including the logic for connecting to peers, consistent hashing, and maintaining the set of galaxies.

Galaxy

A Galaxy is a grouping of keys based on a category determined by the user. For example, you might have a galaxy for Users and a galaxy for Video Metadata; those data types may require different fetching protocols on the backend -- separating them into different Galaxies allows for this flexibility.

Each Galaxy contains its own cache space. The cache is immutable; all cache population and eviction is handled by internal logic.

Maincache vs Hotcache

The cache within each galaxy is divided into a "maincache" and a "hotcache".

The "maincache" contains data that the local process is authoritative over. The maincache is always populated whenever data is fetched from the backend (with a LRU eviction policy).

In order to eliminate network hops, a portion of the cache space in each process is reserved for especially popular keys that the local process is not authoritative over. By default, this "hotcache" is populated by a key and its associated data by means of a requests-per-second metric. The logic for hotcache promotion can be configured by implementing a custom solution with the ShouldPromote.Interface.

Step-by-Step Breakdown of a Get()

galaxycache Caching Example Diagram

When Get is called for a key in a Galaxy in some process called Process_A:

  1. The local cache (both maincache and hotcache) in Process_A is checked first
  2. On a cache miss, the PeerPicker object delegates to the peer authoritative over the requested key
  3. Depends on which peer is authoritative over this key...
  • If the Process_A is the authority:
    • Process_A uses its BackendGetter to get the data, and populates its local maincache
  • If Process_A is not the authority:
    • Process_A calls Fetch on the authoritative remote peer, Process_B (method determined by FetchProtocol)
    • Process_B then performs a Get to either find the data from its own local cache or use the specified BackendGetter to get the data from elsewhere, such as by querying a database
    • Process_B populates its maincache with the data before serving it back to Process_A
    • Process_A determines whether the key is hot enough to promote to the hotcache
      • If it is, then the hotcache for Process_A is populated with the key/data
  1. The data is unmarshaled into the Codec passed into Get

Changes from groupcache

Our changes include the following:

  • Overhauled API to improve usability and configurability
  • Improvements to testing by removing global state
  • Improvement to connection efficiency between peers with the addition of gRPC
  • Added a Promoter.Interface for choosing which keys get hotcached
  • Made some core functionality more generic (e.g. replaced the Sink object with a Codec marshaler interface, removed Byteview)

New architecture and API

No more global state

  • Removed all global variables to allow for multithreaded testing by implementing a Universe container that holds the [Galaxies] (previously a global groups map) and PeerPicker (part of what used to be HTTPPool)
  • Added methods to Universe to allow for simpler handling of most galaxycache operations (setting Peers, instantiating a Picker, etc)

New structure for fetching from peers (with gRPC support)

A smarter Hotcache with configurable promotion logic

  • New default promotion logic uses key access statistics tied to every key to make decisions about populating the hotcache
  • Promoter package provides a ShouldPromote.Interface for creating your own method to determine whether a key should be added to the hotcache
  • Newly added candidate cache keeps track of peer-owned keys (without associated data) that have not yet been promoted to the hotcache
  • Provided variadic options for Galaxy construction to override default promotion logic (with your promoter, max number of candidates, and relative hotcache size to maincache)

Comparison to memcached

See: https://github.com/golang/groupcache/blob/master/README.md

Help

Use the golang-nuts mailing list for any discussion or questions.

# Packages

Package consistenthash provides an implementation of a ring hash.
No description provided by the author
No description provided by the author
No description provided by the author
Package lru implements an LRU cache.
No description provided by the author
No description provided by the author
Package singleflight provides a duplicate function call suppression mechanism.
No description provided by the author

# Functions

NewUniverse is the main constructor for the Universe object.
NewUniverseWithOpts is a deprecated constructor for the Universe object that defines a non-default hash function and number of replicas.
WithHashOpts sets the HashOptions on a universe.
WithHotCacheRatio allows the client to specify a ratio for the main-to-hot cache sizes for the galaxy; defaults to 8:1.
WithMaxCandidates allows the client to specify the size of the candidate cache by the max number of candidates held at one time; defaults to 100.
WithPromoter allows the client to specify a promoter for the galaxy; defaults to a simple QPS comparison.
WithRecorder allows you to override the default stats.Recorder used for stats.

# Constants

CandidateCache is the cache for peer-owned keys that may become popular enough to put in the HotCache.
HotCache is the cache for items that seem popular enough to replicate to this node, even though it's not the owner.
MainCache is the cache for items that this peer is the owner of.

# Variables

AllViews is a slice of default views for people to use.
CacheLevelKey tags the level at which data was found on Get.
CacheTypeKey tags the galaxy sub-cache the metric applies to.
GalaxyKey tags the name of the galaxy.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.
Opencensus stats.

# Structs

CacheStats are returned by stats accessors on Galaxy.
A Galaxy is a cache namespace and associated data spread over a group of 1 or more machines.
GalaxyStats are per-galaxy statistics.
HashOptions specifies the the hash function and the number of replicas for consistent hashing.
HCStatsWithTime includes a time stamp along with the hotcache stats to ensure updates happen no more than once per second.
NullFetchProtocol implements FetchProtocol, but always returns errors.
PeerPicker is in charge of dealing with peers: it contains the hashing options (hash function and number of replicas), consistent hash map of peers, and a map of RemoteFetchers to those peers.
Universe defines the primary container for all galaxycache operations.

# Interfaces

A BackendGetter loads data for a key.
Codec includes both the BinaryMarshaler and BinaryUnmarshaler interfaces.
FetchProtocol defines the chosen fetching protocol to peers (namely HTTP or GRPC) and implements the instantiation method for that connection (creating a new RemoteFetcher).
GalaxyOption is an interface for implementing functional galaxy options.
RemoteFetcher is the interface that must be implemented to fetch from other peers; the PeerPicker contains a map of these fetchers corresponding to each other peer address.

# Type aliases

An AtomicInt is an int64 to be accessed atomically.
ByteCodec is a byte slice type that implements Codec.
CacheType represents a type of cache.
CopyingByteCodec is a byte slice type that implements Codec and returns a copy of the bytes when marshaled.
A GetterFunc implements BackendGetter with a function.
StringCodec is a string type that implements Codec.
UniverseOpt is a functional Universe option.