Skip to content

Commit 639fc50

Browse files
committed
Merge branch 'main' into DOC-4137
2 parents 860944a + 50c39d8 commit 639fc50

File tree

34 files changed

+1183
-57
lines changed

34 files changed

+1183
-57
lines changed

build/components/markdown.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def make_command_linkifier(commands: dict, name: str):
138138
def linkifier(m):
139139
command = m.group(1)
140140
if command in commands and command not in exclude:
141-
return f'[`{command}`](/commands/{command_filename(command)})'
141+
return f'[`{command}`]({{{{< relref "/commands/{command_filename(command)}" >}}}})'
142142
else:
143143
return m.group(0)
144144
return linkifier

build/update_cmds.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env python3
2+
from components.syntax import Command
3+
from components.markdown import Markdown
4+
import json
5+
6+
if __name__ == '__main__':
7+
with open('data/commands_core.json', 'r') as f:
8+
j = json.load(f)
9+
10+
board = []
11+
for k in j:
12+
v = j.get(k)
13+
c = Command(k, v)
14+
sf = c.syntax()
15+
path = f'content/commands/{k.lower().replace(" ", "-")}/'
16+
md = Markdown(f'{path}index.md')
17+
md.fm_data |= v
18+
md.fm_data.update({
19+
'syntax_str': str(c),
20+
'syntax_fmt': sf,
21+
})
22+
if 'replaced_by' in md.fm_data:
23+
replaced = md.generate_commands_links(k, j, md.fm_data['replaced_by'])
24+
md.fm_data['replaced_by'] = replaced
25+
md.persist()

content/commands/json.strlen/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ is JSONPath to specify. Default is root `$`, if not provided. Returns null if th
4949

5050
## Return
5151

52-
JSON.STRLEN returns by recursive descent an array of integer replies for each path, the array's length, or `nil`, if the matching JSON value is not a string.
52+
JSON.STRLEN returns by recursive descent an array of integer replies for each path, the string's length, or `nil`, if the matching JSON value is not a string.
5353
For more information about replies, see [Redis serialization protocol specification]({{< relref "/develop/reference/protocol-spec" >}}).
5454

5555
## Examples

content/commands/readwrite/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ command_flags:
1818
- stale
1919
- fast
2020
complexity: O(1)
21-
description: Enables read-write queries for a connection to a Reids Cluster replica
21+
description: Enables read-write queries for a connection to a Redis Cluster replica
2222
node.
2323
group: cluster
2424
hidden: false
2525
linkTitle: READWRITE
2626
since: 3.0.0
27-
summary: Enables read-write queries for a connection to a Reids Cluster replica node.
27+
summary: Enables read-write queries for a connection to a Redis Cluster replica node.
2828
syntax_fmt: READWRITE
2929
syntax_str: ''
3030
title: READWRITE
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
categories:
3+
- docs
4+
- develop
5+
- stack
6+
- oss
7+
- rs
8+
- rc
9+
- oss
10+
- kubernetes
11+
- clients
12+
description: Server-assisted, client-side caching in Redis
13+
linkTitle: Client-side caching
14+
title: Client-side caching introduction
15+
weight: 20
16+
---
17+
18+
*Client-side caching* reduces network traffic between
19+
a Redis client and the server, which generally improves performance.
20+
See [Client-side caching compatibility with Redis Software and Redis Cloud]({{< relref "operate/rs/references/compatibility/client-side-caching" >}})
21+
for details on Redis versions that support client-side caching.
22+
23+
By default, an [application server](https://en.wikipedia.org/wiki/Application_server)
24+
(which sits between the user app and the database) contacts the
25+
Redis database server through the client library for every read request.
26+
The diagram below shows the flow of communication from the user app,
27+
through the application server to the database and back again:
28+
29+
{{< image filename="images/csc/CSCNoCache.drawio.svg" >}}
30+
31+
When you use client-side caching, the client library
32+
maintains a local cache of data items as it retrieves them
33+
from the database. When the same items are needed again, the client
34+
can satisfy the read requests from the cache instead of the database:
35+
36+
{{< image filename="images/csc/CSCWithCache.drawio.svg" >}}
37+
38+
Accessing the cache is much faster than communicating with the database over the
39+
network and it reduces network traffic. Client-side caching reduces
40+
the load on the database server, so you may be able to run it using less hardware
41+
resources.
42+
43+
As with other forms of [caching](https://en.wikipedia.org/wiki/Cache_(computing)),
44+
client-side caching works well in the very common use case where a small subset of the data
45+
is accessed much more frequently than the rest of the data (according
46+
to the [Pareto principle](https://en.wikipedia.org/wiki/Pareto_principle)).
47+
48+
## Updating the cache when the data changes
49+
50+
All caching systems must implement a scheme to update data in the cache
51+
when the corresponding data changes in the main database. Redis uses an
52+
approach called *tracking*.
53+
54+
When client-side caching is enabled, the Redis server remembers or *tracks* the set of keys
55+
that each client connection has previously read. This includes cases where the client
56+
reads data directly, as with the [`GET`]({{< relref "/commands/get" >}})
57+
command, and also where the server calculates values from the stored data,
58+
as with [`STRLEN`]({{< relref "/commands/strlen" >}}). When any client
59+
writes new data to a tracked key, the server sends an invalidation message
60+
to all clients that have accessed that key previously. This message warns
61+
the clients that their cached copies of the data are no longer valid and the clients
62+
will evict the stale data in response. Next time a client reads from
63+
the same key, it will access the database directly and refresh its cache
64+
with the updated data.
65+
66+
The sequence diagram below shows how two clients might interact as they
67+
access and update the same key:
68+
69+
{{< image filename="images/csc/CSCSeqDiagram.drawio.svg" >}}
70+
71+
## Which commands can cache data?
72+
73+
All read-only commands (with the `@read`
74+
[ACL category]({{< relref "/operate/oss_and_stack/management/security/acl" >}}))
75+
will use cached data, except for the following:
76+
77+
- Any commands for
78+
[probabilistic data types]({{< relref "/develop/data-types/probabilistic" >}}).
79+
These types are designed to be updated frequently, which means that caching
80+
has little or no benefit.
81+
- Non-deterministic commands such as [`HGETALL`]({{< relref "/commands/hgetall" >}}),
82+
[`HSCAN`]({{< relref "/commands/hscan" >}}),
83+
and [`ZRANDMEMBER`]({{< relref "/commands/zrandmember" >}}). By design, these commands
84+
give different results each time they are called.
85+
- Search and query commands (with the `FT.*` prefix), such as
86+
[`FT.SEARCH`]({{< baseurl >}}/commands/ft.search).
87+
88+
You can use the [`MONITOR`]({{< relref "/commands/monitor" >}}) command to
89+
check the server's behavior when you are using client-side caching. Because `MONITOR` only
90+
reports activity from the server, you should find the first cacheable
91+
access to a key causes a response from the server. However, subsequent
92+
accesses are satisfied by the cache, and so `MONITOR` should report no
93+
server activity if client-side caching is working correctly.
94+
95+
## What data gets cached for a command?
96+
97+
Broadly speaking, the data from the specific response to a command invocation
98+
gets cached after it is used for the first time. Subsets of that data
99+
or values calculated from it are retrieved from the server as usual and
100+
then cached separately. For example:
101+
102+
- The whole string retrieved by [`GET`]({{< relref "/commands/get" >}})
103+
is added to the cache. Parts of the same string retrieved by
104+
[`SUBSTR`]({{< relref "/commands/substr" >}}) are calculated on the
105+
server the first time and then cached separately from the original
106+
string.
107+
- Using [`GETBIT`]({{< relref "/commands/getbit" >}}) or
108+
[`BITFIELD`]({{< relref "/commands/bitfield" >}}) on a string
109+
caches the returned values separately from the original string.
110+
- For composite data types accessed by keys
111+
([hash]({{< relref "/develop/data-types/hashes" >}}),
112+
[JSON]({{< relref "/develop/data-types/json" >}}),
113+
[set]({{< relref "/develop/data-types/sets" >}}), and
114+
[sorted set]({{< relref "/develop/data-types/sorted-sets" >}})),
115+
the whole object is cached separately from the individual fields.
116+
So the results of `JSON.GET mykey $` and `JSON.GET mykey $.myfield` create
117+
separate entries in the cache.
118+
- Ranges from [lists]({{< relref "/develop/data-types/lists" >}}),
119+
[streams]({{< relref "/develop/data-types/streams" >}}),
120+
and [sorted sets]({{< relref "/develop/data-types/sorted-sets" >}})
121+
are cached separately from the object they form a part of. Likewise,
122+
subsets returned by [`SINTER`]({{< relref "/commands/sinter" >}}) and
123+
[`SDIFF`]({{< relref "/commands/sdiff" >}}) create separate cache entries.
124+
- For multi-key read commands such as [`MGET`]({{< relref "/commands/mget" >}}),
125+
the ordering of the keys is significant. For example `MGET name:1 name:2` is
126+
cached separately from `MGET name:2 name:1` because the server returns the
127+
values in the order you specify.
128+
- Boolean or numeric values calculated from data types (for example
129+
[`SISMEMBER`]({{< relref "/commands/sismember" >}})) and
130+
[`LLEN`]({{< relref "/commands/llen" >}}) are cached separately from the
131+
object they refer to.
132+
133+
## Usage recommendations
134+
135+
Like any caching system, client-side caching has some limitations:
136+
137+
- The cache has only a limited amount of memory available. When the limit
138+
is reached, the client must *evict* potentially useful items from the
139+
cache to make room for new ones.
140+
- Cache misses, tracking, and invalidation messages always add a slight
141+
performance penalty.
142+
143+
Below are some guidelines to help you use client-side caching efficiently, within these
144+
limitations:
145+
146+
- **Use a separate connection for data that is not cache-friendly**:
147+
Caching gives the most benefit
148+
for keys that are read frequently and updated infrequently. However, you
149+
may also have data, such as counters and scoreboards, that receives frequent
150+
updates. In cases like this, the performance overhead of the invalidation
151+
messages can be greater than the savings made by caching. Avoid this problem
152+
by using a separate connection *without* client-side caching for any data that is
153+
not cache-friendly.
154+
- **Estimate how many items you can cache**: The client libraries let you
155+
specify the maximum number of items you want to hold in the cache. You
156+
can calculate an estimate for this number by dividing the
157+
maximum desired size of the
158+
cache in memory by the average size of the items you want to store
159+
(use the [`MEMORY USAGE`]({{< relref "/commands/memory-usage" >}})
160+
command to get the memory footprint of a key). For example, if you had
161+
10MB (or 10485760 bytes) available for the cache, and the average
162+
size of an item was 80 bytes, you could fit approximately
163+
10485760 / 80 = 131072 items in the cache. Monitor memory usage
164+
on your server with a realistic test load to adjust your estimate
165+
up or down.
166+
167+
## Reference
168+
169+
The Redis server implements extra features for client-side caching that are not used by
170+
the main Redis clients, but may be useful for custom clients and other
171+
advanced applications. See
172+
[Client-side caching reference]({{< relref "/develop/reference/client-side-caching" >}})
173+
for a full technical guide to all the options available for client-side caching.

content/develop/connect/clients/java/jedis.md

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ To include `Jedis` as a dependency in your application, edit the dependency file
3333
<dependency>
3434
<groupId>redis.clients</groupId>
3535
<artifactId>jedis</artifactId>
36-
<version>5.1.2</version>
36+
<version>5.2.0</version>
3737
</dependency>
3838
```
3939

@@ -45,7 +45,7 @@ To include `Jedis` as a dependency in your application, edit the dependency file
4545
}
4646
//...
4747
dependencies {
48-
implementation 'redis.clients:jedis:5.1.2'
48+
implementation 'redis.clients:jedis:5.2.0'
4949
//...
5050
}
5151
```
@@ -196,6 +196,119 @@ public class Main {
196196
}
197197
```
198198

199+
## Connect using client-side caching
200+
201+
Client-side caching is a technique to reduce network traffic between
202+
the client and server, resulting in better performance. See
203+
[Client-side caching introduction]({{< relref "/develop/connect/clients/client-side-caching" >}})
204+
for more information about how client-side caching works and how to use it effectively.
205+
206+
To enable client-side caching, specify the
207+
[RESP3]({{< relref "/develop/reference/protocol-spec#resp-versions" >}})
208+
protocol and pass a cache configuration object during the connection.
209+
210+
The example below shows the simplest client-side caching connection to the default host and port,
211+
`localhost:6379`.
212+
All of the connection variants described above accept these parameters, so you can
213+
use client-side caching with a connection pool or a cluster connection in exactly the same way.
214+
215+
{{< note >}}Client-side caching requires Jedis v5.2.0 or later.
216+
To maximize compatibility with all Redis products, client-side caching
217+
is supported by Redis v7.4 or later.
218+
{{< /note >}}
219+
220+
```java
221+
HostAndPort endpoint = new HostAndPort("localhost", 6379);
222+
223+
DefaultJedisClientConfig config = DefaultJedisClientConfig
224+
.builder()
225+
.password("secretPassword")
226+
.protocol(RedisProtocol.RESP3)
227+
.build();
228+
229+
CacheConfig cacheConfig = CacheConfig.builder().maxSize(1000).build();
230+
231+
UnifiedJedis client = new UnifiedJedis(endpoint, config, cacheConfig);
232+
```
233+
234+
Once you have connected, the usual Redis commands will work transparently
235+
with the cache:
236+
237+
```java
238+
client.set("city", "New York");
239+
client.get("city"); // Retrieved from Redis server and cached
240+
client.get("city"); // Retrieved from cache
241+
```
242+
243+
You can see the cache working if you connect to the same Redis database
244+
with [`redis-cli`]({{< relref "/develop/connect/cli" >}}) and run the
245+
[`MONITOR`]({{< relref "/commands/monitor" >}}) command. If you run the
246+
code above but without passing `cacheConfig` during the connection,
247+
you should see the following in the CLI among the output from `MONITOR`:
248+
249+
```
250+
1723109720.268903 [...] "SET" "city" "New York"
251+
1723109720.269681 [...] "GET" "city"
252+
1723109720.270205 [...] "GET" "city"
253+
```
254+
255+
The server responds to both `get("city")` calls.
256+
If you run the code with `cacheConfig` added in again, you will see
257+
258+
```
259+
1723110248.712663 [...] "SET" "city" "New York"
260+
1723110248.713607 [...] "GET" "city"
261+
```
262+
263+
The first `get("city")` call contacted the server, but the second
264+
call was satisfied by the cache.
265+
266+
### Removing items from the cache
267+
268+
You can remove individual keys from the cache with the
269+
`deleteByRedisKey()` method of the cache object. This removes all cached items associated
270+
with each specified key, so all results from multi-key commands (such as
271+
[`MGET`]({{< relref "/commands/mget" >}})) and composite data structures
272+
(such as [hashes]({{< relref "/develop/data-types/hashes" >}})) will be
273+
cleared at once. The example below shows the effect of removing a single
274+
key from the cache:
275+
276+
```java
277+
client.hget("person:1", "name"); // Read from the server
278+
client.hget("person:1", "name"); // Read from the cache
279+
280+
client.hget("person:2", "name"); // Read from the server
281+
client.hget("person:2", "name"); // Read from the cache
282+
283+
Cache myCache = client.getCache();
284+
myCache.deleteByRedisKey("person:1");
285+
286+
client.hget("person:1", "name"); // Read from the server
287+
client.hget("person:1", "name"); // Read from the cache
288+
289+
client.hget("person:2", "name"); // Still read from the cache
290+
```
291+
292+
You can also clear all cached items using the `flush()`
293+
method:
294+
295+
```java
296+
client.hget("person:1", "name"); // Read from the server
297+
client.hget("person:1", "name"); // Read from the cache
298+
299+
client.hget("person:2", "name"); // Read from the server
300+
client.hget("person:2", "name"); // Read from the cache
301+
302+
Cache myCache = client.getCache();
303+
myCache.flush();
304+
305+
client.hget("person:1", "name"); // Read from the server
306+
client.hget("person:1", "name"); // Read from the cache
307+
308+
client.hget("person:2", "name"); // Read from the server
309+
client.hget("person:2", "name"); // Read from the cache
310+
```
311+
199312
## Production usage
200313

201314
The following sections explain how to handle situations that may occur

0 commit comments

Comments
 (0)