-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Initialize an mkdocs-based Jedis doc site #3998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
b85f9fe
28a306c
c7e2897
0f1a9aa
21ceed5
3ae5f89
da1dab8
c1c1c23
2fe1e7c
1d71872
68345e8
853c328
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| name: Publish Docs | ||
| on: | ||
| push: | ||
| branches: ["master"] | ||
| permissions: | ||
| contents: read | ||
| pages: write | ||
| id-token: write | ||
| concurrency: | ||
| group: "pages" | ||
| cancel-in-progress: false | ||
| jobs: | ||
| build-and-deploy: | ||
| concurrency: ci-${{ github.ref }} | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v3 | ||
| - uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: 3.9 | ||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install mkdocs mkdocs-material pymdown-extensions mkdocs-macros-plugin | ||
| - name: Build docs | ||
| run: | | ||
| mkdocs build -d docsbuild | ||
| - name: Setup Pages | ||
| uses: actions/configure-pages@v3 | ||
| - name: Upload artifact | ||
| uses: actions/upload-pages-artifact@v1 | ||
| with: | ||
| path: 'docsbuild' | ||
| - name: Deploy to GitHub Pages | ||
| id: deployment | ||
| uses: actions/deploy-pages@v2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| FROM squidfunk/mkdocs-material | ||
| RUN pip install mkdocs-macros-plugin | ||
| RUN pip install mkdocs-glightbox |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Jedis Documentation | ||
|
|
||
| This documenation uses [MkDocs](https://www.mkdocs.org/) to generate the static site. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. documenation |
||
|
|
||
| See [mkdocs.yml](../mkdocs.yml) for the configuration. | ||
|
|
||
| To develop the documentation locally, you can use the included [Dockefile](ockerfile) to build a container with all the | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dockefile |
||
| dependencies, and run it to preview your changes: | ||
|
|
||
| ```bash | ||
| # in docs/ | ||
| docker build -t squidfunk/mkdocs-material . | ||
| # cd .. | ||
| docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| # Advanced Usage | ||
|
|
||
| ## Transactions | ||
|
|
||
| To do transactions in Jedis, you have to wrap operations in a transaction block, very similar to pipelining: | ||
|
|
||
| ```java | ||
| jedis.watch (key1, key2, ...); | ||
| Transaction t = jedis.multi(); | ||
| t.set("foo", "bar"); | ||
| t.exec(); | ||
| ``` | ||
|
|
||
| Note: when you have any method that returns values, you have to do like this: | ||
|
|
||
|
|
||
| ```java | ||
| Transaction t = jedis.multi(); | ||
| t.set("fool", "bar"); | ||
| Response<String> result1 = t.get("fool"); | ||
|
|
||
| t.zadd("foo", 1, "barowitch"); t.zadd("foo", 0, "barinsky"); t.zadd("foo", 0, "barikoviev"); | ||
| Response<Set<String>> sose = t.zrange("foo", 0, -1); // get the entire sortedset | ||
| t.exec(); // dont forget it | ||
|
|
||
| String foolbar = result1.get(); // use Response.get() to retrieve things from a Response | ||
| int soseSize = sose.get().size(); // on sose.get() you can directly call Set methods! | ||
|
|
||
| // List<Object> allResults = t.exec(); // you could still get all results at once, as before | ||
| ``` | ||
| Note that a Response Object does not contain the result before t.exec() is called (it is a kind of a Future). Forgetting exec gives you exceptions. In the last lines, you see how transactions/pipelines were dealt with before version 2. You can still do it that way, but then you need to extract objects from a list, which contains also Redis status messages. | ||
|
|
||
| Note 2: Redis does not allow to use intermediate results of a transaction within that same transaction. This does not work: | ||
|
|
||
| ```java | ||
| // this does not work! Intra-transaction dependencies are not supported by Redis! | ||
| jedis.watch(...); | ||
| Transaction t = jedis.multi(); | ||
| if(t.get("key1").equals("something")) | ||
| t.set("key2", "value2"); | ||
| else | ||
| t.set("key", "value"); | ||
| ``` | ||
|
|
||
| However, there are some commands like setnx, that include such a conditional execution. Those are of course supported within transactions. You can build your own customized commands using eval/ LUA scripting. | ||
|
|
||
|
|
||
| ## Pipelining | ||
|
|
||
| Sometimes you need to send a bunch of different commands. A very cool way to do that, and have better performance than doing it the naive way, is to use pipelining. This way you send commands without waiting for response, and you actually read the responses at the end, which is faster. | ||
|
|
||
| Here is how to do it: | ||
|
|
||
| ```java | ||
| Pipeline p = jedis.pipelined(); | ||
| p.set("fool", "bar"); | ||
| p.zadd("foo", 1, "barowitch"); p.zadd("foo", 0, "barinsky"); p.zadd("foo", 0, "barikoviev"); | ||
| Response<String> pipeString = p.get("fool"); | ||
| Response<Set<String>> sose = p.zrange("foo", 0, -1); | ||
| p.sync(); | ||
|
|
||
| int soseSize = sose.get().size(); | ||
| Set<String> setBack = sose.get(); | ||
| ``` | ||
| For more explanations see code comments in the transaction section. | ||
|
|
||
|
|
||
| ## Publish/Subscribe | ||
|
|
||
| To subscribe to a channel in Redis, create an instance of JedisPubSub and call subscribe on the Jedis instance: | ||
|
|
||
| ```java | ||
| class MyListener extends JedisPubSub { | ||
| public void onMessage(String channel, String message) { | ||
| } | ||
|
|
||
| public void onSubscribe(String channel, int subscribedChannels) { | ||
| } | ||
|
|
||
| public void onUnsubscribe(String channel, int subscribedChannels) { | ||
| } | ||
|
|
||
| public void onPSubscribe(String pattern, int subscribedChannels) { | ||
| } | ||
|
|
||
| public void onPUnsubscribe(String pattern, int subscribedChannels) { | ||
| } | ||
|
|
||
| public void onPMessage(String pattern, String channel, String message) { | ||
| } | ||
| } | ||
|
|
||
| MyListener l = new MyListener(); | ||
|
|
||
| jedis.subscribe(l, "foo"); | ||
| ``` | ||
| Note that subscribe is a blocking operation because it will poll Redis for responses on the thread that calls subscribe. A single JedisPubSub instance can be used to subscribe to multiple channels. You can call subscribe or psubscribe on an existing JedisPubSub instance to change your subscriptions. | ||
|
|
||
|
|
||
| ### Monitoring | ||
|
|
||
| To use the monitor command you can do something like the following: | ||
|
|
||
| ```java | ||
| new Thread(new Runnable() { | ||
| public void run() { | ||
| Jedis j = new Jedis("localhost"); | ||
| for (int i = 0; i < 100; i++) { | ||
| j.incr("foobared"); | ||
| try { | ||
| Thread.sleep(200); | ||
| } catch (InterruptedException e) { | ||
| } | ||
| } | ||
| j.disconnect(); | ||
| } | ||
| }).start(); | ||
|
|
||
| jedis.monitor(new JedisMonitor() { | ||
| public void onCommand(String command) { | ||
| System.out.println(command); | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| ## Miscellaneous | ||
|
|
||
| ### A note about String and Binary - what is native? | ||
|
|
||
| Redis/Jedis talks a lot about Strings. And here [[http://redis.io/topics/internals]] it says Strings are the basic building block of Redis. However, this stress on strings may be misleading. Redis' "String" refer to the C char type (8 bit), which is incompatible with Java Strings (16-bit). Redis sees only 8-bit blocks of data of predefined length, so normally it doesn't interpret the data (it's "binary safe"). Therefore in Java, byte[] data is "native", whereas Strings have to be encoded before being sent, and decoded after being retrieved by the SafeEncoder. This has some minor performance impact. | ||
| In short: if you have binary data, don't encode it into String, but use the binary versions. | ||
|
|
||
| ### A note on Redis' master/slave distribution | ||
|
|
||
| A Redis network consists of redis servers, which can be either masters or slaves. Slaves are synchronized to the master (master/slave replication). However, master and slaves look identical to a client, and slaves do accept write requests, but they will not be propagated "up-hill" and could eventually be overwritten by the master. It makes sense to route reads to slaves, and write demands to the master. Furthermore, being a slave doesn't prevent from being considered master by another slave. |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file should be ignored from spell check. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| /* extra.css */ | ||
| .md-header { | ||
| background-color: #FB2A2C; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Frequently Asked Questions | ||
|
|
||
| ## If you get `java.net.SocketTimeoutException: Read timed out` exception | ||
|
|
||
| Try setting own `timeout` value when constructing `JedisPool` using the following constructor: | ||
| ```java | ||
| JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout) | ||
| ``` | ||
| where `timeout` is given as milliseconds. | ||
|
|
||
| Default `timeout` value is **2 seconds**. | ||
|
|
||
| ## JedisPool blocks after getting 8 connections | ||
|
|
||
| JedisPool defaults to 8 connections, you can change this in the PoolConfig: | ||
|
|
||
| ```java | ||
| JedisPoolConfig poolConfig = new JedisPoolConfig(); | ||
| poolConfig.setMaxTotal(maxTotal); // maximum active connections | ||
| poolConfig.setMaxIdle(maxIdle); // maximum idle connections | ||
| ``` | ||
|
|
||
| Take into account that `JedisPool` inherits commons-pool [BaseObjectPoolConfig](https://commons.apache.org/proper/commons-pool/api-2.3/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html) which has a lot of configuration parameters. | ||
| We've set some defined ones which suit most of the cases. In case, you experience [issues](https://github.com/xetorthio/jedis/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+JedisPool) tuning these parameters may help. | ||
|
|
||
| ## How to configure the buffer size of socket(s) | ||
|
|
||
| The buffer size of all Jedis sockets in an application can be configured through system property. | ||
|
|
||
| Buffer size of input stream can be configured by setting `jedis.bufferSize.input` or `jedis.bufferSize` system property. | ||
| Buffer size of output stream can be configured by setting `jedis.bufferSize.output` or `jedis.bufferSize` system property. | ||
| If you want to set the buffer size of both input and output stream to same value, you can just set `jedis.bufferSize`. | ||
|
|
||
| Note: This feature is available since Jedis 4.2.0. | ||
|
|
||
| ## How to avoid cluster initialization error | ||
|
|
||
| As of Jedis 4.0.0, a `JedisClusterOperationException` is raised with the message `Could not initialize cluster slots cache.` when the cluster initialization process fails. | ||
|
|
||
| Should you would want to avoid this error (for example, creating `JedisConnectionFactory` to an unavailable cluster for a spring-data-redis `Bean`), set the system property `jedis.cluster.initNoError` to any value. | ||
| In the console, add the option `-Djedis.cluster.initNoError`. | ||
| In an application, `System.setProperty("jedis.cluster.initNoError", "");` can be set before creating any cluster object. | ||
|
|
||
| Note: This feature is available since Jedis 4.4.2. |
joshrotenberg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| # Getting Started | ||
|
|
||
| ## Installing Jedis | ||
| In order to have Jedis as a dependency in your application you can: | ||
| ### Use the jar files | ||
| Download the latest [Jedis](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22redis.clients%22%20AND%20a%3A%22jedis%22) and [Apache Commons Pool2](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.apache.commons%22%20AND%20a%3A%22commons-pool2%22) jars from [search.maven.org](http://search.maven.org) or any other maven repository. | ||
|
|
||
| ### Build from source | ||
| This gives you the most recent version. | ||
| #### Clone the GitHub project. | ||
| That is very easy, on the command line you just need to: | ||
| ```git clone git://github.com/xetorthio/jedis.git``` | ||
| #### Build from GitHub | ||
| Before you package it using maven, you have to pass the tests. | ||
| To run the tests and package, run ```make package```. | ||
|
|
||
| ### Configure a Maven dependency | ||
| Jedis is also distributed as a Maven Dependency through Sonatype. To configure that just add the following XML snippet to your pom.xml file. | ||
|
|
||
| ```xml | ||
| <dependency> | ||
| <groupId>redis.clients</groupId> | ||
| <artifactId>jedis</artifactId> | ||
| <version>2.9.0</version> | ||
| <type>jar</type> | ||
| <scope>compile</scope> | ||
| </dependency> | ||
| ``` | ||
| ## Basic usage example | ||
| ### using Jedis in a multithreaded environment | ||
| You shouldn't use the same instance from different threads because you'll have strange errors. | ||
| And sometimes creating lots of Jedis instances is not good enough because it means lots of sockets and connections, which leads to strange errors as well. | ||
| ```A single Jedis instance is not threadsafe!``` | ||
| To avoid these problems, you should use JedisPool, which is a threadsafe pool of network connections. | ||
| You can use the pool to reliably create several Jedis instances, given you return the Jedis instance to the pool when done. This way you can overcome those strange errors and achieve great performance. | ||
|
|
||
| To use it, init a pool: | ||
| ```java | ||
| JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost"); | ||
| ``` | ||
|
|
||
| You can store the pool somewhere statically, it is thread-safe. | ||
|
|
||
| JedisPoolConfig includes a number of helpful Redis-specific connection pooling defaults. JedisPool is based on Commons Pool 2, so you may want to have a look at Commons Pool's configuration. Please see http://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/GenericObjectPoolConfig.html for more details. | ||
|
|
||
| You use it by: | ||
|
|
||
| ```java | ||
| /// Jedis implements Closeable. Hence, the jedis instance will be auto-closed after the last statement. | ||
| try (Jedis jedis = pool.getResource()) { | ||
| /// ... do stuff here ... for example | ||
| jedis.set("foo", "bar"); | ||
| String foobar = jedis.get("foo"); | ||
| jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike"); | ||
| Set<String> sose = jedis.zrange("sose", 0, -1); | ||
| } | ||
| /// ... when closing your application: | ||
| pool.close(); | ||
| ``` | ||
|
|
||
| If you can't use try-with-resource, you can still enjoy with Jedis.close(). | ||
|
|
||
| ```java | ||
| Jedis jedis = null; | ||
| try { | ||
| jedis = pool.getResource(); | ||
| /// ... do stuff here ... for example | ||
| jedis.set("foo", "bar"); | ||
| String foobar = jedis.get("foo"); | ||
| jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike"); | ||
| Set<String> sose = jedis.zrange("sose", 0, -1); | ||
| } finally { | ||
| // You have to close jedis object. If you don't close then | ||
| // it doesn't release back to pool and you can't get a new | ||
| // resource from pool. | ||
| if (jedis != null) { | ||
| jedis.close(); | ||
| } | ||
| } | ||
| /// ... when closing your application: | ||
| pool.close(); | ||
| ``` | ||
|
|
||
| If Jedis was borrowed from pool, it will be returned to pool with proper method since it already determines there was JedisConnectionException occurred. | ||
| If Jedis wasn't borrowed from pool, it will be disconnected and closed. | ||
|
|
||
| ### Setting up master/slave distribution | ||
| #### enable replication | ||
| Redis is primarily built for master/slave distribution. This means that write requests have to be explicitly addressed to the master (a redis server), which replicates changes to slaves (which are also redis servers). Read requests then can be (but must not necessarily) addressed to the slaves, which alleviates the master. | ||
|
|
||
| You use the master as shown above. In order to enable replication, there are two ways to tell a slave it will be "slaveOf" a given master: | ||
|
|
||
| * Specify it in the respective section in the Redis Config file of the redis server | ||
|
|
||
| * on a given jedis instance (see above), call the slaveOf method and pass IP (or "localhost") and port as argument: | ||
|
|
||
| ```java | ||
| jedis.slaveof("localhost", 6379); // if the master is on the same PC which runs your code | ||
| jedis.slaveof("192.168.1.35", 6379); | ||
| ``` | ||
|
|
||
| Note: since Redis 2.6 slaves are read only by default, so write requests to them will result in an error. | ||
|
|
||
| If you change that setting they will behave like normal redis servers and accept write requests without errors, but the changes won't be replicated, and hence those changes are at risk to be silently overwritten, if you mix up your jedis instances. | ||
|
|
||
| #### disable replication / upon failing master, promote a slave | ||
|
|
||
| In case your master goes down, you may want to promote a slave to be the new master. You should first (try to) disable replication of the offline master first, then, in case you have several slaves, enable replication of the remaining slaves to the new master: | ||
|
|
||
| ```java | ||
| slave1jedis.slaveofNoOne(); | ||
| slave2jedis.slaveof("192.168.1.36", 6379); | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {% include 'README.md' %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should be ignored from spell check.