1
1
# groupcache
2
2
3
+ A modified version of [ group cache] ( https://github.com/golang/groupcache ) with
4
+ support for ` context.Context ` , [ go modules] ( https://github.com/golang/go/wiki/Modules ) ,
5
+ and explicit key removal and expiration. See the ` CHANGELOG ` for a complete list of
6
+ modifications.
7
+
3
8
## Summary
4
9
5
10
groupcache is a caching and cache-filling library, intended as a
6
11
replacement for memcached in many cases.
7
12
8
13
For API docs and examples, see http://godoc.org/github.com/mailgun/groupcache
9
14
10
- ## Comparison to memcached
15
+
16
+ ### Modifications from original library
17
+
18
+ * Support for explicit key removal from a group. ` Remove() ` requests are
19
+ first sent to the peer who owns the key, then the remove request is
20
+ forwarded to every peer in the groupcache. NOTE: This is a best case design
21
+ since it is possible a temporary network disruption could occur resulting
22
+ in remove requests never making it their peers. In practice this scenario
23
+ is very rare and the system remains very consistent. In case of an
24
+ inconsistency placing a expiration time on your values will ensure the
25
+ cluster eventually becomes consistent again.
26
+
27
+ * Support for expired values. ` SetBytes() ` , ` SetProto() ` and ` SetString() ` now
28
+ accept an optional ` time.Time{} ` which represents a time in the future when the
29
+ value will expire. Expiration is handled by the LRU Cache when a ` Get() ` on a
30
+ key is requested. This means no network coordination of expired values is needed.
31
+ However this does require that time on all nodes in the cluster is synchronized
32
+ for consistent expiration of values.
33
+
34
+ * Network methods now accept golang standard ` context.Context ` instead of
35
+ ` groupcache.Context ` .
36
+
37
+ * Now always populating the hotcache. A more complex algorithm is unnecessary
38
+ when the LRU cache will ensure the most used values remain in the cache. The
39
+ evict code ensures the hotcache never overcrowds the maincache.
40
+
41
+ ## Comparing Groupcache to memcached
11
42
12
43
### ** Like memcached** , groupcache:
13
44
@@ -28,16 +59,7 @@ For API docs and examples, see http://godoc.org/github.com/mailgun/groupcache
28
59
the loaded value to all callers.
29
60
30
61
* does not support versioned values. If key "foo" is value "bar",
31
- key "foo" must always be "bar". There are neither cache expiration
32
- times, nor explicit cache evictions. Thus there is also no CAS,
33
- nor Increment/Decrement. This also means that groupcache....
34
-
35
- * ... supports automatic mirroring of super-hot items to multiple
36
- processes. This prevents memcached hot spotting where a machine's
37
- CPU and/or NIC are overloaded by very popular keys/values.
38
-
39
- * is currently only available for Go. It's very unlikely that I
40
- (bradfitz@) will port the code to any other language.
62
+ key "foo" must always be "bar".
41
63
42
64
## Loading process
43
65
@@ -58,16 +80,76 @@ In a nutshell, a groupcache lookup of **Get("foo")** looks like:
58
80
the answer. If the RPC fails, just load it locally (still with
59
81
local dup suppression).
60
82
61
- ## Users
62
-
63
- groupcache is in production use by dl.google.com (its original user),
64
- parts of Blogger, parts of Google Code, parts of Google Fiber, parts
65
- of Google production monitoring systems, etc.
66
-
67
- ## Presentations
68
-
69
- See http://talks.golang.org/2013/oscon-dl.slide
70
-
71
- ## Help
83
+ ## Example
84
+
85
+ ``` go
86
+ import (
87
+ " context"
88
+ " fmt"
89
+ " log"
90
+ " time"
91
+
92
+ " github.com/mailgun/groupcache/v2"
93
+ )
94
+
95
+ func ExampleUsage () {
96
+ // Keep track of peers in our cluster and add our instance to the pool `http://localhost:8080`
97
+ pool := groupcache.NewHTTPPoolOpts (" http://localhost:8080" , &groupcache.HTTPPoolOptions {})
98
+
99
+ // Add more peers to the cluster
100
+ // pool.Set("http://peer1:8080", "http://peer2:8080")
101
+
102
+ server := http.Server {
103
+ Addr: " localhost:8080" ,
104
+ Handler: pool,
105
+ }
106
+
107
+ // Start a HTTP server to listen for peer requests from the groupcache
108
+ go func () {
109
+ log.Printf (" Serving....\n " )
110
+ if err := server.ListenAndServe (); err != nil {
111
+ log.Fatal (err)
112
+ }
113
+ }()
114
+ defer server.Shutdown (context.Background ())
115
+
116
+ // Create a new group cache with a max cache size of 3MB
117
+ group := groupcache.NewGroup (" users" , 3000000 , groupcache.GetterFunc (
118
+ func (ctx context.Context , id string , dest groupcache.Sink ) error {
119
+
120
+ // Returns a protobuf struct `User`
121
+ if user , err := fetchUserFromMongo (ctx, id); err != nil {
122
+ return err
123
+ }
124
+
125
+ // Set the user in the groupcache to expire after 5 minutes
126
+ if err := dest.SetProto (&user, time.Now ().Add (time.Minute *5 )); err != nil {
127
+ return err
128
+ }
129
+ return nil
130
+ },
131
+ ))
132
+
133
+ var user User
134
+
135
+ ctx , cancel := context.WithTimeout (context.Background (), time.Millisecond *500 )
136
+ defer cancel ()
137
+
138
+ if err := group.Get (ctx, " 12345" , groupcache.ProtoSink (&user)); err != nil {
139
+ log.Fatal (err)
140
+ }
141
+
142
+ fmt.Printf (" -- User --\n " )
143
+ fmt.Printf (" Id: %s \n " , user.Id )
144
+ fmt.Printf (" Name: %s \n " , user.Name )
145
+ fmt.Printf (" Age: %d \n " , user.Age )
146
+ fmt.Printf (" IsSuper: %t \n " , user.IsSuper )
147
+
148
+ // Remove the key from the groupcache
149
+ if err := group.Remove (ctx, " 12345" ); err != nil {
150
+ log.Fatal (err)
151
+ }
152
+ }
153
+
154
+ ```
72
155
73
- Use the golang-nuts mailing list for any discussion or questions.
0 commit comments