From 665c46309808214aed9270cc0b903c25cc650d6b Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 4 Apr 2025 09:40:41 +0100 Subject: [PATCH 1/9] DOC-5064 started checklist implementation --- content/develop/clients/jedis/produsage.md | 12 +++- layouts/shortcodes/checklist-item.html | 14 +++++ layouts/shortcodes/checklist.html | 71 ++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 layouts/shortcodes/checklist-item.html create mode 100644 layouts/shortcodes/checklist.html diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index eadd8c10bc..2bca26172b 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -16,7 +16,17 @@ weight: 6 --- The following sections explain how to handle situations that may occur -in your production environment. +in your production environment. Use the checklist below to record your +progress in implementing the recommendations. + +{{< checklist "prodlist" >}} + {{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}} + {{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}} + {{< checklist-item "#general-exceptions" >}}General exceptions{{< /checklist-item >}} + {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} +{{< /checklist >}} + + ### Timeouts diff --git a/layouts/shortcodes/checklist-item.html b/layouts/shortcodes/checklist-item.html new file mode 100644 index 0000000000..3315ca55b0 --- /dev/null +++ b/layouts/shortcodes/checklist-item.html @@ -0,0 +1,14 @@ +
  • + +{{- if index .Params 0 -}} +{{ .Inner }} +{{- else -}} +{{ .Inner }} +{{- end -}} +
  • \ No newline at end of file diff --git a/layouts/shortcodes/checklist.html b/layouts/shortcodes/checklist.html new file mode 100644 index 0000000000..6f405af311 --- /dev/null +++ b/layouts/shortcodes/checklist.html @@ -0,0 +1,71 @@ +{{ $formId := index .Params 0 }} +
    + + + 0/, + + 2/, + + 0/
    + ( + 0/) +
    + \ No newline at end of file From e0c14cbd9f938a8fa9b97404509356ee5b2be127 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 4 Apr 2025 12:01:43 +0100 Subject: [PATCH 2/9] DOC-5064 added checklist storage --- content/develop/clients/jedis/produsage.md | 3 +- layouts/shortcodes/checklist.html | 99 +++++++++++++++------- 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 2bca26172b..75d492d43d 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -23,7 +23,8 @@ progress in implementing the recommendations. {{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}} {{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}} {{< checklist-item "#general-exceptions" >}}General exceptions{{< /checklist-item >}} - {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} + {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} + {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} {{< /checklist >}} diff --git a/layouts/shortcodes/checklist.html b/layouts/shortcodes/checklist.html index 6f405af311..3c8b3e5802 100644 --- a/layouts/shortcodes/checklist.html +++ b/layouts/shortcodes/checklist.html @@ -6,44 +6,25 @@ 0/, - 2/, + 0/, - 0/
    + 0/ +
    ( 0/) \ No newline at end of file From b2f5c9914b78c551bc0af5a6128b56e31aa896a3 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Mon, 7 Apr 2025 11:10:55 +0100 Subject: [PATCH 3/9] DOC-5064 finished checklist and added some new sections --- content/develop/clients/jedis/produsage.md | 57 +++++++++++++++++++--- layouts/shortcodes/checklist-item.html | 3 +- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 75d492d43d..89311b0b65 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -15,23 +15,62 @@ title: Production usage weight: 6 --- -The following sections explain how to handle situations that may occur -in your production environment. Use the checklist below to record your +This guide offers recommendations to get the best reliability and +performance in your production environment. + +## Checklist + +Each item in the checklist below links to the section +for a recommendation. Use the checklist icons to record your progress in implementing the recommendations. +[](#client-side-caching) {{< checklist "prodlist" >}} + {{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}} + {{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}} {{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}} {{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}} - {{< checklist-item "#general-exceptions" >}}General exceptions{{< /checklist-item >}} - {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} {{< /checklist >}} +## Recommendations + +The sections below offer recommendations for your production environment. Some +of them may not apply to your particular use case. + +### Connection pooling +Example code often opens a connection at the start, demonstrates a feature, +and then closes the connection at the end. However, production code +typically uses connections many times intermittently. Repeatedly opening +and closing connections has a performance overhead. + +Use [connection pooling]({{< relref "/develop/clients/pools-and-muxing" >}}) +to avoid the overhead of opening and closing connections without having to +write your own code to cache and reuse open connections. See +[Connect with a connection pool]({{< relref "/develop/clients/jedis/connect#connect-with-a-connection-pool" >}}) +to learn how to use this technique with Jedis. + +### Client-side caching + +[Client-side caching]({{< relref "/develop/clients/client-side-caching" >}}) +involves storing the results from read-only commands in a local cache. If the +same command is executed again later, the result can be obtained from the cache, +without contacting the server. This improves command execution time on the client, +while also reducing network traffic and server load. See +[Connect using client-side caching]({{< relref "/develop/clients/jedis/connect#connect-using-client-side-caching" >}}) +for more information and example code. ### Timeouts -To set a timeout for a connection, use the `JedisPooled` or `JedisPool` constructor with the `timeout` parameter, or use `JedisClientConfig` with the `socketTimeout` and `connectionTimeout` parameters: +If a network or server error occurs while your code is opening a +connection or issuing a command, it can end up hanging indefinitely. +You can prevent this from happening by setting timeouts for socket +reads and writes and for opening connections. + +To set a timeout for a connection, use the `JedisPooled` or `JedisPool` constructor with the `timeout` parameter, or use `JedisClientConfig` with the `socketTimeout` and `connectionTimeout` parameters. +(The socket timeout is the maximum time allowed for reading or writing data while executing a +command. The connection timeout is the maximum time allowed for establishing a new connection.) ```java HostAndPort hostAndPort = new HostAndPort("localhost", 6379); @@ -47,7 +86,13 @@ JedisPooled jedisWithTimeout = new JedisPooled(hostAndPort, ### Exception handling -The Jedis Exception Hierarchy is rooted on `JedisException`, which implements `RuntimeException`, and are therefore all unchecked exceptions. +Redis handles many errors using return values from commands, but there +are also situations where exceptions can be thrown. In production code, +you should handle + +The Jedis exception hierarchy is rooted on `JedisException`, which implements +`RuntimeException`. All exceptions in the hierarchy are therefore unchecked +exceptions. ``` JedisException diff --git a/layouts/shortcodes/checklist-item.html b/layouts/shortcodes/checklist-item.html index 3315ca55b0..6536881725 100644 --- a/layouts/shortcodes/checklist-item.html +++ b/layouts/shortcodes/checklist-item.html @@ -1,6 +1,5 @@
  • - From 7490d773aae026a6b7c68d39de228cfef36b1f40 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Tue, 8 Apr 2025 12:40:39 +0100 Subject: [PATCH 4/9] DOC-5064 added health checks and TCP keepalive --- content/develop/clients/jedis/produsage.md | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 89311b0b65..bd7ffda144 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -29,6 +29,8 @@ progress in implementing the recommendations. {{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}} {{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}} {{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}} + {{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}} + {{< checklist-item "#tcp-keepalive" >}}TCP keepalive{{< /checklist-item >}} {{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}} {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} {{< /checklist >}} @@ -84,6 +86,45 @@ JedisPooled jedisWithTimeout = new JedisPooled(hostAndPort, ); ``` +### Health checks + +If your code doesn't access the Redis server continuously then it +might be useful to make a "health check" periodically (perhaps once +every few seconds). You can do this using a simple +[`PING`]({{< relref "/commands/ping" >}}) command: + +```java +try (Jedis jedis = jedisPool.getResource()) { + if (! "PONG".equals(jedis.ping())) { + // Report problem. + } +} +``` + +Health checks help to detect problems as soon as possible without +waiting for a user to report them. + +### TCP keepalive + +[TCP keepalive](https://en.wikipedia.org/wiki/Keepalive) is a technique +where TCP packets are periodically sent on an otherwise idle connection +to check that it is still working. You can enable TCP keepalive for a +connection using an option on the connection config builder: + +```java +JedisClientConfig clientConfig = DefaultJedisClientConfig.builder() + .connectionTimeoutMillis(2000) + .socketTimeoutMillis(2000) + .tcpKeepAlive(true) + .build(); + +JedisPool pool = new JedisPool(poolConfig, "redis-host", clientConfig); +``` + +TCP keepalive can be especially useful to detect when unused connections +in a [connection pool](#connection-pooling) have been dropped due to +inactivity. + ### Exception handling Redis handles many errors using return values from commands, but there From 55dbd02c2ce6666f4a4b59e9d26cd1e27fd19e0e Mon Sep 17 00:00:00 2001 From: andy-stark-redis <164213578+andy-stark-redis@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:13:21 +0100 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: David Dougherty --- content/develop/clients/jedis/produsage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index bd7ffda144..6f30d9309d 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -57,7 +57,7 @@ to learn how to use this technique with Jedis. [Client-side caching]({{< relref "/develop/clients/client-side-caching" >}}) involves storing the results from read-only commands in a local cache. If the -same command is executed again later, the result can be obtained from the cache, +same command is executed again later, the results can be obtained from the cache, without contacting the server. This improves command execution time on the client, while also reducing network traffic and server load. See [Connect using client-side caching]({{< relref "/develop/clients/jedis/connect#connect-using-client-side-caching" >}}) @@ -129,7 +129,7 @@ inactivity. Redis handles many errors using return values from commands, but there are also situations where exceptions can be thrown. In production code, -you should handle +you should handle exceptions as they occur. The Jedis exception hierarchy is rooted on `JedisException`, which implements `RuntimeException`. All exceptions in the hierarchy are therefore unchecked From 14d1400e76db0d301c09597292cf72c5e24920f3 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 11 Apr 2025 09:08:34 +0100 Subject: [PATCH 6/9] DOC-5064 removed unused code and markup --- content/develop/clients/jedis/produsage.md | 1 - layouts/shortcodes/checklist.html | 27 ---------------------- 2 files changed, 28 deletions(-) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index bd7ffda144..37b548ddd6 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -24,7 +24,6 @@ Each item in the checklist below links to the section for a recommendation. Use the checklist icons to record your progress in implementing the recommendations. -[](#client-side-caching) {{< checklist "prodlist" >}} {{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}} {{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}} diff --git a/layouts/shortcodes/checklist.html b/layouts/shortcodes/checklist.html index 3c8b3e5802..685c3422d4 100644 --- a/layouts/shortcodes/checklist.html +++ b/layouts/shortcodes/checklist.html @@ -23,33 +23,6 @@ clChange("{{ $formId }}"); } }); - - /* - function clChange(formId) { - let form = document.getElementById(formId); - let counts = {R: 0, G: 0, A: 0, X:0}; - - let listItems = form.getElementsByTagName("li"); - - for (let elem of listItems) { - let menu = elem.getElementsByTagName("select")[0]; - let mvalue = menu.value; - - counts[mvalue]++; - } - - form.elements["rcount"].value = counts["R"]; - form.elements["gcount"].value = counts["G"]; - form.elements["acount"].value = counts["A"]; - form.elements["xcount"].value = counts["X"]; - - let numClItems = listItems.length - counts["X"]; - form.elements["rtotal"].value = numClItems; - form.elements["gtotal"].value = numClItems; - form.elements["atotal"].value = numClItems; - form.elements["xtotal"].value = listItems.length; - } - */ function getStringFromCLItems(formId) { From 1a36cd4fac9d8ad909d6783a61c68d725040cae0 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 11 Apr 2025 09:14:14 +0100 Subject: [PATCH 7/9] Revert "DOC-5064 removed unused code and markup" This reverts commit 14d1400e76db0d301c09597292cf72c5e24920f3. --- content/develop/clients/jedis/produsage.md | 1 + layouts/shortcodes/checklist.html | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 37b548ddd6..bd7ffda144 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -24,6 +24,7 @@ Each item in the checklist below links to the section for a recommendation. Use the checklist icons to record your progress in implementing the recommendations. +[](#client-side-caching) {{< checklist "prodlist" >}} {{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}} {{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}} diff --git a/layouts/shortcodes/checklist.html b/layouts/shortcodes/checklist.html index 685c3422d4..3c8b3e5802 100644 --- a/layouts/shortcodes/checklist.html +++ b/layouts/shortcodes/checklist.html @@ -23,6 +23,33 @@ clChange("{{ $formId }}"); } }); + + /* + function clChange(formId) { + let form = document.getElementById(formId); + let counts = {R: 0, G: 0, A: 0, X:0}; + + let listItems = form.getElementsByTagName("li"); + + for (let elem of listItems) { + let menu = elem.getElementsByTagName("select")[0]; + let mvalue = menu.value; + + counts[mvalue]++; + } + + form.elements["rcount"].value = counts["R"]; + form.elements["gcount"].value = counts["G"]; + form.elements["acount"].value = counts["A"]; + form.elements["xcount"].value = counts["X"]; + + let numClItems = listItems.length - counts["X"]; + form.elements["rtotal"].value = numClItems; + form.elements["gtotal"].value = numClItems; + form.elements["atotal"].value = numClItems; + form.elements["xtotal"].value = listItems.length; + } + */ function getStringFromCLItems(formId) { From bdf109cf8eac7ccac5221a5575c1d4a5279d8bad Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 11 Apr 2025 09:16:40 +0100 Subject: [PATCH 8/9] DOC-5064 removed unused stuff --- content/develop/clients/jedis/produsage.md | 1 - layouts/shortcodes/checklist.html | 27 ---------------------- 2 files changed, 28 deletions(-) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 6f30d9309d..4ca6845e11 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -24,7 +24,6 @@ Each item in the checklist below links to the section for a recommendation. Use the checklist icons to record your progress in implementing the recommendations. -[](#client-side-caching) {{< checklist "prodlist" >}} {{< checklist-item "#connection-pooling" >}}Connection pooling{{< /checklist-item >}} {{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}} diff --git a/layouts/shortcodes/checklist.html b/layouts/shortcodes/checklist.html index 3c8b3e5802..685c3422d4 100644 --- a/layouts/shortcodes/checklist.html +++ b/layouts/shortcodes/checklist.html @@ -23,33 +23,6 @@ clChange("{{ $formId }}"); } }); - - /* - function clChange(formId) { - let form = document.getElementById(formId); - let counts = {R: 0, G: 0, A: 0, X:0}; - - let listItems = form.getElementsByTagName("li"); - - for (let elem of listItems) { - let menu = elem.getElementsByTagName("select")[0]; - let mvalue = menu.value; - - counts[mvalue]++; - } - - form.elements["rcount"].value = counts["R"]; - form.elements["gcount"].value = counts["G"]; - form.elements["acount"].value = counts["A"]; - form.elements["xcount"].value = counts["X"]; - - let numClItems = listItems.length - counts["X"]; - form.elements["rtotal"].value = numClItems; - form.elements["gtotal"].value = numClItems; - form.elements["atotal"].value = numClItems; - form.elements["xtotal"].value = listItems.length; - } - */ function getStringFromCLItems(formId) { From 3636c568c8ae6344de2a865628bf1b8432fc48fe Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Wed, 30 Apr 2025 10:24:06 +0100 Subject: [PATCH 9/9] DOC-5064 removed incorrect tcpKeepAlive section --- content/develop/clients/jedis/produsage.md | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/content/develop/clients/jedis/produsage.md b/content/develop/clients/jedis/produsage.md index 4ca6845e11..d78a94193e 100644 --- a/content/develop/clients/jedis/produsage.md +++ b/content/develop/clients/jedis/produsage.md @@ -29,7 +29,6 @@ progress in implementing the recommendations. {{< checklist-item "#client-side-caching" >}}Client-side caching{{< /checklist-item >}} {{< checklist-item "#timeouts" >}}Timeouts{{< /checklist-item >}} {{< checklist-item "#health-checks" >}}Health checks{{< /checklist-item >}} - {{< checklist-item "#tcp-keepalive" >}}TCP keepalive{{< /checklist-item >}} {{< checklist-item "#exception-handling" >}}Exception handling{{< /checklist-item >}} {{< checklist-item "#dns-cache-and-redis" >}}DNS cache and Redis{{< /checklist-item >}} {{< /checklist >}} @@ -103,27 +102,6 @@ try (Jedis jedis = jedisPool.getResource()) { Health checks help to detect problems as soon as possible without waiting for a user to report them. -### TCP keepalive - -[TCP keepalive](https://en.wikipedia.org/wiki/Keepalive) is a technique -where TCP packets are periodically sent on an otherwise idle connection -to check that it is still working. You can enable TCP keepalive for a -connection using an option on the connection config builder: - -```java -JedisClientConfig clientConfig = DefaultJedisClientConfig.builder() - .connectionTimeoutMillis(2000) - .socketTimeoutMillis(2000) - .tcpKeepAlive(true) - .build(); - -JedisPool pool = new JedisPool(poolConfig, "redis-host", clientConfig); -``` - -TCP keepalive can be especially useful to detect when unused connections -in a [connection pool](#connection-pooling) have been dropped due to -inactivity. - ### Exception handling Redis handles many errors using return values from commands, but there