Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: filter/dscache/doc.go

Issue 1269113005: A transparent cache for datastore, backed by memcache. (Closed) Base URL: https://github.com/luci/gae.git@add_meta
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Package dscache provides a transparent cache for RawDatastore which is
6 // backed by Memcache.
7 //
8 // Inspiration
9 //
10 // Although this is not a port of any particular implementation, it takes
11 // inspiration from these fine libraries:
12 // - https://cloud.google.com/appengine/docs/python/ndb/
13 // - https://github.com/qedus/nds
14 // - https://github.com/mjibson/goon
15 //
16 // Algorithm
17 //
18 // Memcache contains cache entries for single datastore entities. The memcache
19 // key looks like
20 //
21 // "gae:" | vers | ":" | shard | ":" | Base64_std_nopad(SHA1(rawdatastore.Key) )
22 //
23 // Where:
24 // - vers is an ascii-hex-encoded number (currently 1).
25 // - shard is a zero-based ascii-hex-encoded number (depends on dscache.shards ).
26 // - SHA1 has been chosen as unlikely (p == 1e-18) to collide, given dedicated
27 // memcache sizes of up to 170 Exabytes (assuming an average entry size of
28 // 100KB including the memcache key). This is clearly overkill, but MD5
29 // could start showing collisions at this probability in as small as a 26GB
30 // cache (and also MD5 sucks).
31 //
32 // The memcache value is a compression byte, indicating the scheme (See
33 // CompressionType), followed by the encoded (and possibly compressed) value.
34 // Encoding is done with rawdatastore.PropertyMap.Write(). The memcache value
35 // may also be the empty byte sequence, indicating that this entity is deleted.
36 //
37 // The memcache entry may also have a 'flags' value set to one of the following:
38 // - 0 "entity" (cached value)
39 // - 1 "lock" (someone is mutating this entry)
40 //
41 // Algorithm - Put and Delete
42 //
43 // On a Put (or Delete), the memcache value written with a LockTimeSeconds
44 // expiration (default 31 seconds), and a memcache flag value of 0x1 (indicating
45 // that it's a put-locked key).
46 //
47 // The datastore operation will then occur. Assuming success, Put will then
48 // delete all of the memcache locks (Not using CompareAndSwap).
49 //
50 // Algorithm - Get
51 //
52 // On a Get, "Add" a lock for it (which only does something if there's no entry
53 // in memcache yet) with a nonce value. We immediately Get the memcache entries
54 // back (for CAS purposes later).
55 //
56 // If it doesn't exist (unlikely since we just Add'd it) or if it's flag is
57 // "lock" and the Value != the nonce we put there, go hit the datastore without
58 // trying to update memcache.
59 //
60 // If its flag is "entity", decode the object and return it. If the Value is
61 // the empty byte sequence, return ErrNoSuchEntity.
62 //
63 // If its flag is "lock" and the Value equals the nonce, go get it from the
64 // datastore. If that's successful, then encode the value to bytes, and CAS
65 // the object to memcache. The CAS will succeed if nothing else touched the
66 // memcache in the meantime (like a Put, a memcache expiration/eviction, etc.).
67 //
68 // Algorithm - Transactions
69 //
70 // In a transaction, all Put memcache operations are held until the very end of
71 // the transaction. Right before the transaction is committed, all accumulated
72 // Put keys are locked. If the transaction is sucessfully committed (err ==
73 // nil), then all the locks will be deleted.
74 //
75 // The assumption here is that get operations apply all outstanding
76 // transactions before they return data (https://cloud.google.com/appengine/docs /go/datastore/#Go_Datastore_writes_and_data_visibility),
77 // and so it is safe to purge all the locks if the transaction is known-good.
78 //
79 // If the transaction succeeds, but RunInTransaction returns an error (which can
80 // happen), or if the transaction fails, then the lock entries time out
81 // naturally. This will mean 31-ish seconds of direct datastore access, but it's
82 // the more-correct thing to do.
83 //
84 // Cache control
85 //
86 // An entity may expose the following metadata (see
87 // rawdatastore.PropertyLoadSaver.GetMeta) to control the behavior of its cache.
88 //
89 // - "dscache.enable,<true|false>" - whether or not this entity should be
90 // cached at all. If ommitted, dscache defaults to true.
91 // - "dscache.expiration,#seconds" - the number of seconds of persistance to
92 // use when this item is cached. 0 is infinite. If omitted, defaults to 0.
93 //
94 // In addition, the application may set a function ShardsForKey(key) which
95 // returns the number of shards to use for a given datastore key.
96 //
97 // Caveats
98 //
99 // A couple things to note that may differ from other appengine datastore
100 // caching libraries (like goon, nds, or ndb).
101 //
102 // - It does NOT provide in-memory ("per-request") caching.
103 // - It's tolerant of memcache failures (but will give potentially
104 // inconsistent results if memcache is non-operational). Using a transaction
105 // bypasses the cache logic, which will present a consistent view of the dat a.
106 // - Queries do not interact with the cache at all.
107 // - Negative lookups (e.g. ErrNoSuchEntity) are cached.
108 // - Allows sharding hot memcache entries as recommended by
109 // https://cloud.google.com/appengine/articles/best-practices-for-app-engine -memcache#distribute-load .
110 package dscache
OLDNEW
« no previous file with comments | « filter/dscache/context.go ('k') | filter/dscache/ds.go » ('j') | filter/dscache/dscache_test.go » ('J')

Powered by Google App Engine
This is Rietveld 408576698