Documentation
¶
Overview ¶
Package mirror is a blob store that keeps each blob on several member stores at once (decision 0028): different clouds, regions or accounts, any mix of the fs, s3, gcs and azure backends.
Writes go to Redundancy members in parallel and succeed once WriteQuorum of them hold the blob; members still committing get MemberTimeout to finish in the background, and every member's outcome is recorded in the replica index (store.ReplicaIndex) as present or pending, so the repair worker can fill missing copies later. Reads use the index to go straight to a member holding the blob, in read order: this instance's zone first, then by observed latency, members whose breaker is open last. A read that fails part-way reopens on the next holder at the same offset, which is safe because blobs are immutable.
This is Artifactory's sharding provider (redundancy, lenientLimit, zone-aware reads) with three differences: members may be any backend in any cloud, an index records which members hold which blob instead of every read probing every shard, and surplus copies are never deleted automatically.
Index ¶
- Constants
- Variables
- type Member
- type MemberStatus
- type Options
- type RemovedMember
- type RepairReport
- type Status
- type Store
- func (s *Store) BeginUpload(ctx context.Context, opts ...blob.UploadOption) (blob.Upload, error)
- func (s *Store) Delete(ctx context.Context, sha string) error
- func (s *Store) Exists(ctx context.Context, sha string) (bool, error)
- func (s *Store) Open(ctx context.Context, sha string) (io.ReadSeekCloser, blob.Info, error)
- func (s *Store) Repair(ctx context.Context) (RepairReport, error)
- func (s *Store) ResumeUpload(ctx context.Context, id string) (blob.Upload, error)
- func (s *Store) RunRepair(ctx context.Context, every time.Duration, trigger <-chan struct{}) error
- func (s *Store) SignURL(ctx context.Context, sha string, o blob.SignOptions) (string, error)
- func (s *Store) Signs(via blob.Via) bool
- func (s *Store) Stat(ctx context.Context, sha string) (blob.Info, error)
- func (s *Store) Status(ctx context.Context) (Status, error)
- func (s *Store) WaitIdle(ctx context.Context) error
- func (s *Store) Walk(ctx context.Context, fn func(blob.Info) error) error
Constants ¶
const ( // DefaultMemberTimeout is how long members still committing after the // quorum may finish before their copy is left to the repair worker. DefaultMemberTimeout = 30 * time.Second // DefaultChunkSize is the smallest chunk New derives. A chunk is the // buffer one upload hands to every member at once, so a mirrored upload // holds one chunk in memory, not one per member. DefaultChunkSize = 8 << 20 // MaxDerivedChunkSize caps the chunk New derives from the members' part // sizes. Part sizes whose least common multiple is larger (5, 7 and 11 // MiB need 385 MiB) would cost that much memory per upload, and are // almost certainly a mistake. MaxDerivedChunkSize = 256 << 20 // DefaultBreakerThreshold is the consecutive failures that open a // member's breaker. DefaultBreakerThreshold = 5 // DefaultBreakerCooldown is how long an open breaker stays open before a // call is let through again; Artifactory's state-aware providers re-check // a failed store after the same 15 seconds (checkPeriod). DefaultBreakerCooldown = 15 * time.Second // DefaultRepairBatch is how many replicas one repair pass works on per // step, so a pass holds its lease for a bounded time. DefaultRepairBatch = 100 // DefaultRepairMaxAttempts is how many failed copies make a pending // replica failed, for an operator to look at. DefaultRepairMaxAttempts = 10 // DefaultRepairBackoff is the wait after a replica's first failed // attempt; it doubles with every attempt up to maxRepairBackoff, so a // copy that keeps failing is not retried in a tight loop. DefaultRepairBackoff = time.Minute )
Defaults for the zero Options fields.
const DefaultRepairInterval = time.Minute
DefaultRepairInterval is how often RunRepair runs a pass when no interval is given.
Variables ¶
var ( // ErrConfig reports an unusable configuration. ErrConfig = errors.New("blob/mirror: invalid configuration") // ErrQuorum reports a write that fewer than WriteQuorum members accepted. ErrQuorum = errors.New("blob/mirror: write quorum not met") )
Sentinel errors. Test with errors.Is.
var ErrSeek = errors.New("blob/mirror: invalid seek")
ErrSeek reports an invalid Seek.
Functions ¶
This section is empty.
Types ¶
type Member ¶
type Member struct {
// Name identifies the member in the replica index; it must stay stable.
Name string
// Zone places the member, for example "aws-eu-west-1"; members in the
// instance's zone are read and written first.
Zone string
// Store is the member's blob store.
Store blob.Store
// WriteEnabled lets the member receive new copies. A member with it
// false is drained: it serves reads but gets nothing new.
WriteEnabled bool
// Kind names the member's backend (fs, s3, gcs, azure) for Status; the
// mirror itself does not use it.
Kind string
}
Member is one store of the mirror.
type MemberStatus ¶
type MemberStatus struct {
Name, Zone, Kind string
WriteEnabled bool
// Available is false while the member's breaker is open: reads and
// writes go to the other members first.
Available bool
// Latency is the weighted average of recent successful calls; zero
// before the first one.
Latency time.Duration
// Replicas are the member's replica records per state, ordered by state.
Replicas []store.ReplicaCount
// SoleCopies counts the blobs whose only present copy is on this
// member. A drained member (WriteEnabled false) is safe to remove from
// the configuration once it is zero.
SoleCopies int64
}
MemberStatus is one member's view in Status.
type Options ¶
type Options struct {
Members []Member
// Redundancy is how many members keep each blob; zero means every
// member (a full mirror).
Redundancy int
// WriteQuorum is how many members must store a blob before an upload
// succeeds. Zero means Redundancy-1 (at least 1): by default an upload
// still succeeds with one member down, which is the outage the mirror
// exists to ride out, and the missing copy is repaired later.
WriteQuorum int
// Zone is this instance's zone.
Zone string
// MemberTimeout bounds how long members may finish after the quorum;
// zero means DefaultMemberTimeout.
MemberTimeout time.Duration
// ChunkSize is the fan-out buffer. Zero derives it: the smallest
// multiple of every member's part size (blob.PartSizer) that is at least
// DefaultChunkSize, so the s3 and azure defaults (8 MiB) with the gcs
// default (16 MiB) give 16 MiB. An explicit size must be a multiple of
// every member's part size.
ChunkSize int64
// Sessions keeps the mirror's own upload sessions (the member upload
// IDs). Members keep their own sessions.
Sessions session.Store
// Replicas records which members hold which blobs.
Replicas store.ReplicaIndex
// BreakerThreshold and BreakerCooldown tune each member's breaker; zero
// means the defaults.
BreakerThreshold int
BreakerCooldown time.Duration
// Now supplies the time for the breaker, latency and replica records;
// nil means time.Now.
Now func() time.Time
// The repair worker's settings (repair.go). Blobs and Leases are only
// required by Repair: a mirror that never repairs may leave them nil.
//
// Blobs is the blob index whose reference counts tell a deferred delete
// whether the blob was uploaded again since.
Blobs store.BlobIndex
// Leases holds the lease that keeps two repair passes from overlapping.
Leases store.LeaseStore
// RepairLease names the lease a pass holds; empty means
// "blob-mirror-repair". Two mirrors sharing a lease store (the hot and
// cold tiers) need different names, or each pass of one skips the other.
RepairLease string
// RepairBatch, RepairMaxAttempts and RepairBackoff tune a pass; zero
// means the defaults.
RepairBatch int
RepairMaxAttempts int
RepairBackoff time.Duration
// OnRepair, when set, receives every pass RunRepair makes, so the server
// can log or count them.
OnRepair func(RepairReport, error)
}
Options configures New.
type RemovedMember ¶
type RemovedMember struct {
Name string
// Replicas are its replica records per state, ordered by state.
Replicas []store.ReplicaCount
// SoleCopies counts the blobs whose only present copy is on it.
SoleCopies int64
}
RemovedMember is a member in Status.Removed.
type RepairReport ¶
type RepairReport struct {
// Skipped is set when another pass held the lease; nothing was done.
Skipped bool
// Copied counts pending replicas filled by copying from another member.
Copied int
// Found counts pending replicas whose member already held the blob, for
// example a commit that finished after its record was written.
Found int
// Failed counts attempts that failed this pass.
Failed int
// Deleted counts tombstones whose copy was removed.
Deleted int
// DeletesSkipped counts tombstones of blobs uploaded again since the
// delete, which were kept rather than removed.
DeletesSkipped int
// Backfilled counts pending records added to bring a blob up to the
// redundancy, for example on a newly added member.
Backfilled int
// Drained counts pending records added because a blob's only copies are
// on members no longer accepting writes.
Drained int
}
RepairReport counts what one repair pass did.
type Status ¶
type Status struct {
Redundancy int
WriteQuorum int
// Zone is this instance's zone.
Zone string
// UnderReplicated counts blobs with fewer present copies than
// Redundancy (store.ReplicaIndex.UnderReplicated).
UnderReplicated int64
Members []MemberStatus
// Removed are members with replica records that are no longer
// configured. Repair neither copies to nor reads from them, so a blob
// whose only present copy is on one (SoleCopies) is out of the mirror's
// reach until the member is configured again.
Removed []RemovedMember
}
Status is a mirror's configuration, member health and replica counts, for the storage summary (#18). Artifactory's summary has nothing per shard.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a blob.Store over several member stores.
func (*Store) BeginUpload ¶
BeginUpload starts a session on the members placement chooses.
func (*Store) Delete ¶
Delete removes the blob from every member. A member that cannot be reached keeps a deleting record, a tombstone the repair worker acts on later; reads honour it, so the blob is gone for every reader as soon as Delete returns.
func (*Store) Open ¶
Open returns a reader that serves the blob from the first member that holds it and moves to the next one, at the same offset, if a read fails.
func (*Store) Repair ¶
func (s *Store) Repair(ctx context.Context) (RepairReport, error)
Repair runs one repair pass under the repair lease:
- pending replicas are copied to their member from a member that holds the blob, or marked present when the member already has it;
- deleting tombstones are carried out, unless the blob was uploaded again since the delete;
- blobs with fewer copies on write-enabled members than the redundancy get pending records, which fills a newly added member and moves the copies of a draining one.
Each step works on at most the repair batch, so a pass is bounded. It never deletes a copy because there are too many: removing a member stays an explicit operator action (decision 0028). When another pass holds the lease it returns a report with Skipped set and no error.
func (*Store) ResumeUpload ¶
ResumeUpload reopens a session and each active member's upload. A member whose upload cannot be resumed drops out of the session.
func (*Store) RunRepair ¶
RunRepair runs a repair pass every interval, and at once whenever trigger fires (the storage optimize endpoint sends on it), until ctx ends, then returns ctx's error. Each pass's report and error go to OnRepair when it is set; a failed pass does not stop the loop.
func (*Store) SignURL ¶
SignURL returns a URL from the first member, in read order, that holds the blob and signs o's route. A member's signing failure moves on to the next member but never counts against its health.
func (*Store) Signs ¶
Signs reports whether any member signs URLs for via. Members are fixed when the mirror is built, so the answer is too.
func (*Store) Status ¶
Status reports the mirror's members, their replica records, and the records of members no longer configured.
func (*Store) WaitIdle ¶
WaitIdle waits until the background commits running when it is called have finished and recorded their outcome, or ctx ends. A server calls it on shutdown so a member finishing after the quorum is recorded rather than left pending for no reason; a test calls it before looking at the members.