transferred from: Http://www.baeldung.com/jedis-java-redis-client-library
1. Overview
This article was an introduction to Jedis, a client library in Java for Redis–the popular in-memory data structu Re store that can persist on disk as well. It is driven by a keystore-based data structure to persist data and can be used as a database, cache, message broker, etc.
First, we are going-explain in which kind of situations Jedis was useful and what it was about.
In the subsequent sections we is elaborating on the various data structures and explaining transactions, pipelining and T He publish/subscribe feature. We conclude with connection pooling and Redis Cluster.
2. Why Jedis?
Redis lists the most well-known client libraries on their official site. There is multiple alternatives to Jedis, but only the more is currently worthy of their recommendation star, lettuce, an D Redisson.
These clients do has some unique features like thread safety, transparent reconnection handling and an asynchronous A PI, all features of which Jedis lacks.
However, it's small and considerably faster than the other. Besides, it is the client library of choice of the Spring Framework developers and it have the biggest community of all THR Ee.
3. Maven Dependencies
Let's start by declaring the only dependency we'll need in the pom.xml:
<Dependency> <groupId>Redis.clients</groupId> <Artifactid>Jedis</Artifactid> <version>2.8.1</version></Dependency>
If you ' re looking for the latest version of the library, check out this page.
4. Redis Installation
You'll need to install and fire up one of the latest versions of Redis. We is running the latest stable version at this moment (3.2.1), but no post 3.x version should be okay.
Find here more information on Redis for Linux and Macintosh, they has very similar basic installation steps. Windows is not officially supported it is the well maintained.
Thereafter we can directly dive in and connect to it from our Java code:
New Jedis ();
The default constructor would work just fine unless you had started the service on a Non-default port or on a remote machi NE, in which case you can configure it correctly by passing the correct values as parameters into the constructor.
5. Redis Data Structures
Most of the native operation commands is supported and, conveniently enough, they normally share the same method name.
5.1. Strings
Strings is the most basic kind of Redis value, useful if you need to persist simple key-value data types:
Jedis.set ("Events/city/rome", "32,15,223,828"= Jedis.get ("Events/city/rome");
The variable cachedresponse would hold the value 32,15,223,828. Coupled with expiration support, discussed later, it can work as a lightning fast and simple to use the cache layer for HTTP R Equests received at your Web application and other caching requirements.
5.2. Lists
Redis Lists is simply Lists of strings, sorted by insertion order and make it a ideal tool to implement, for instance, M essage Queues:
Jedis.lpush ("Queue#tasks", "Firsttask"); Jedis.lpush ("Queue#tasks", "secondtask"= Jedis.rpop (" Queue#tasks ");
5.3. Sets
Redis sets is an unordered collection of Strings it come in handy when you want to exclude repeated:
Jedis.sadd ("nicknames", "Nickname#1"), Jedis.sadd ("nicknames", "Nickname#2"); Jedis.sadd (" Nicknames "," Nickname#1 "); Set<String> nicknames = Jedis.smembers ("nicknames"); Boolean exists = Jedis.sismember ("nicknames", "nickname#1");
The Java Set nicknames 'll has a size of 2, the second addition of nickname#1 was ignored. Also, the exists variable would have a value of true, the method Sismember enables your to Quickl Y check for the existence of a particular member.
5.4. Hashes
Redis hashes is mapping between string fields and string values:
Jedis.hset ("User#1", "name", "Peter"), Jedis.hset ("user#1", "job", "politician"= Jedis.hget ("user# 1 "," name "); Map<string, string> fields = Jedis.hgetall ("user#1"= Fields.get ("job");
As can see, hashes is a very convenient data type when you want to access object ' s properties individually since Need to retrieve the whole object.
5.5. Sorted sets
Sorted sets is a Set of where each member have an associated ranking, which is the used for sorting them:
map<string, double> scores = new hashmap<> (); scores.put (" Playerone ", 3000.0" Playertwo ", 1500.0" Playerthree ", 8200.0 -> { jedis.zadd ( "ranking" = Jedis.zrevrange ("ranking", 0, 1 long rank = Jedis.zrevrank ("ranking", "Playerone");
The variable player would hold the value playerthree because we be retrieving the top 1 player and he is The one with the highest score. The rank variable would have a value of 1 because Playerone are the second in the ranking and the ranking Is zero-based.
6. Transactions
Transactions guarantee atomicity and thread safety operations, which means that requests from other clients would never be Handled concurrently during Redis transactions:
String friendsprefix = "friends#"= "4352523"= "5552321"=++ Usertwoid, Useroneid); T.exec ();
You can even make a transaction success dependent in a specific key by "watching" it right before you instantiate your transaction:
Jedis.watch ("friends#deleted#" + Useroneid);
If the value of this key changes before the transaction is executed, the transaction would not be completed successfully.
7. Pipelining
When we had to send multiple commands, we can pack them together on one request and save connection overhead by using PIP Elines, it is essentially a network optimization. As long as the operations is mutually independent, we can take a advantage of this technique:
String Useroneid = "4352523" ; String usertwoid = "4849888" ; pipeline p = jedis.pipelined ();p. Sadd ( "searched#" + Useroneid, "Paris" );p. Zadd (" ranking ", 126" ranking ", 325 <Boolean> pipeexists = P.sismember ("searched#" + Useroneid, "Paris" <Set<String>> piperanking = P.zrange ("ranking", 0, -1 = Pipeexists.get (); Set <String> ranking = Piperanking.get ();
Notice we don't get direct access to the command responses, instead we is given a Responseinstance from which W E can request the underlying response after the pipeline have been synced.
8. Publish/subscribe
We can use the Redis messaging broker functionality to send messages between the different components of our system. Make sure the Subscriber and Publisher threads does not share the same Jedis connection.
8.1. Subscriber
Subscribe and listen to messages sent to a channel:
New Jedis (); Jsubscriber.subscribe (new jedispubsub () {@Override publicvoid onMessage (string channel, String message) { // handle message"channel");
Subscribe is a blocking method, you'll need to unsubscribe from the jedispubsub explicitly. We have overridden the onMessage method But there is many more useful methods available to override.
8.2. Publisher
Then simply send messages to this same channel from the Publisher ' s thread:
New Jedis (); Jpublisher.publish ("channel", "Test Message");
9. Connection Pooling
It's important to know that the the-the-the-been dealing with our Jedis instance are naive. In a real world scenario, you don't want to use a single instance in a multi-threaded environment as a single instance are Not thread safe.
Luckily enough we can easily create a pool of connections to Redis for us to reuse on demand, a pool that is thread safe a nd reliable as long as you return "the resource to the pool" is done with it.
Let ' s create the jedispool:
FinalJedispoolconfig Poolconfig =Buildpoolconfig (); Jedispool Jedispool=NewJedispool (Poolconfig, "localhost"); Privatejedispoolconfig Buildpoolconfig () {FinalJedispoolconfig Poolconfig =NewJedispoolconfig (); Poolconfig.setmaxtotal (128); Poolconfig.setmaxidle (128); Poolconfig.setminidle (16); Poolconfig.settestonborrow (true); Poolconfig.settestonreturn (true); Poolconfig.settestwhileidle (true); Poolconfig.setminevictableidletimemillis (Duration.ofseconds (60). Tomillis ()); Poolconfig.settimebetweenevictionrunsmillis (Duration.ofseconds (30). Tomillis ()); Poolconfig.setnumtestsperevictionrun (3); Poolconfig.setblockwhenexhausted (true); returnPoolconfig;}
Since the pool instance is thread safe and you can store it somewhere statically and you should take care of destroying the P Ool to avoid leaks when the application is being shutdown.
Now we can make use of our pool from anywhere in the application when needed:
Try (Jedis Jedis = Jedispool.getresource ()) { // do operations with Jedis resource}
We used the Java try-with-resources statement to avoid have to manually close the Jedis resource and if you cannot use This statement your can also close the resource manually in the finally clause.
Make sure your use a pool like we had described in your application if you don't want to face nasty multi-threading issue S. You can obviously play with the pool configuration parameters to adapt it to the best setup in your system.
Ten. Redis Cluster
This Redis implementation provides easy scalability and high availability, we encourage your to read their official Specifi cation if you is not a familiar with it. We'll not cover Redis cluster setup since. A bit out of the scope for this article, but you should has no proble MS in doing if you are doing with its documentation.
Once we have this ready, we can start using the it from our application:
Try New Jediscluster (new hostandport ("localhost", 6379))) { // Use the jediscluster resource as If it was a normal Jedis resourcecatch (IOException e) {}
We only need to provide the host and port details from one of our master instances, it'll auto-discover the rest of the Instances in the cluster.
This was certainly a very powerful feature but it was not a silver bullet. When using the Redis Cluster you cannot perform transactions or use pipelines, both important features on which many Applicati ONS rely for ensuring data integrity.
Transactions is disabled because, in a clustered environment, keys would be persisted across multiple instances. Operation Atomicity and thread safety cannot be guaranteed for operations, involve command execution in different inst Ances.
Some Advanced key creation strategies would ensure that data that's interesting for your being persisted in the same Instan Ce would get persisted that. In theory, which should enable you to perform transactions successfully using one of the underlying Jedis instances of the Redis Cluster.
Unfortunately, currently you cannot find out in which Redis instance a particular key was saved using Jedis (which is Actua Lly supported natively by Redis), so don't know which of the instances you must perform the transaction operation. If you is interested about this, you can find more information here.
conclusion.
The vast majority of the features from Redis is already available in Jedis and their development moves forward at a good PA Ce.
It gives ability to integrate a powerful in-memory storage engine in your application with very little hassle, jus t do not forget to set up connection pooling to avoid thread safety issues.
You can find code samples in the GitHub project.
Intro to jedis–the Java Redis Client Library