package redis.clients.jedis;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.JedisCluster.Reset;
import redis.clients.jedis.params.geo.GeoRadiusParam;
import redis.clients.jedis.params.sortedset.ZAddParams;
import redis.clients.jedis.params.sortedset.ZIncrByParams;
import redis.clients.util.Pool;
import redis.clients.util.SafeEncoder;
import redis.clients.util.Slowlog;
import java.net.URI;
import java.util.*;
import java.util.Map.Entry;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocketFactory;
public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommands,
AdvancedJedisCommands, ScriptingCommands, BasicCommands, ClusterCommands, SentinelCommands {
protected Pool<Jedis> dataSource = null;
public Jedis() {
super();
}
public Jedis(final String host) {
super(host);
}
public Jedis(final String host, final int port) {
super(host, port);
}
public Jedis(final String host, final int port, final boolean ssl) {
super(host, port, ssl);
}
public Jedis(final String host, final int port, final boolean ssl,
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
final HostnameVerifier hostnameVerifier) {
super(host, port, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public Jedis(final String host, final int port, final int timeout) {
super(host, port, timeout);
}
public Jedis(final String host, final int port, final int timeout, final boolean ssl) {
super(host, port, timeout, ssl);
}
public Jedis(final String host, final int port, final int timeout, final boolean ssl,
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
final HostnameVerifier hostnameVerifier) {
super(host, port, timeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
}
public Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout) {
super(host, port, connectionTimeout, soTimeout);
}
public Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout,
final boolean ssl) {
super(host, port, connectionTimeout, soTimeout, ssl);
}
public Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout,
final boolean ssl, final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
final HostnameVerifier hostnameVerifier) {
super(host, port, connectionTimeout, soTimeout, ssl, sslSocketFactory, sslParameters,
hostnameVerifier);
}
public Jedis(JedisShardInfo shardInfo) {
super(shardInfo);
}
public Jedis(URI uri) {
super(uri);
}
public Jedis(URI uri, final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
final HostnameVerifier hostnameVerifier) {
super(uri, sslSocketFactory, sslParameters, hostnameVerifier);
}
public Jedis(final URI uri, final int timeout) {
super(uri, timeout);
}
public Jedis(final URI uri, final int timeout, final SSLSocketFactory sslSocketFactory,
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
super(uri, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
}
public Jedis(final URI uri, final int connectionTimeout, final int soTimeout) {
super(uri, connectionTimeout, soTimeout);
}
public Jedis(final URI uri, final int connectionTimeout, final int soTimeout,
final SSLSocketFactory sslSocketFactory, final SSLParameters sslParameters,
final HostnameVerifier hostnameVerifier) {
super(uri, connectionTimeout, soTimeout, sslSocketFactory, sslParameters, hostnameVerifier);
}
/**
* Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
* GB).
* <p>
* Time complexity: O(1)
* @param key
* @param value
* @return Status code reply
*/
public String set(final String key, String value) {
checkIsInMultiOrPipeline();
client.set(key, value);
return client.getStatusCodeReply();
}
/**
* Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
* GB).
* @param key
* @param value
* @param nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key
* if it already exist.
* @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds
* @param time expire time in the units of <code>expx</code>
* @return Status code reply
*/
public String set(final String key, final String value, final String nxxx, final String expx,
final long time) {
checkIsInMultiOrPipeline();
client.set(key, value, nxxx, expx, time);
return client.getStatusCodeReply();
}
/**
* Get the value of the specified key. If the key does not exist null is returned. If the value
* stored at key is not a string an error is returned because GET can only handle string values.
* <p>
* Time complexity: O(1)
* @param key
* @return Bulk reply
*/
public String get(final String key) {
checkIsInMultiOrPipeline();
client.sendCommand(Protocol.Command.GET, key);
return client.getBulkReply();
}
/**
* Test if the specified key exists. The command returns the number of keys existed Time
* complexity: O(N)
* @param keys
* @return Integer reply, specifically: an integer greater than 0 if one or more keys were removed
* 0 if none of the specified key existed
*/
public Long exists(final String... keys) {
checkIsInMultiOrPipeline();
client.exists(keys);
return client.getIntegerReply();
}
/**
* Test if the specified key exists. The command returns "1" if the key exists, otherwise "0" is
* returned. Note that even keys set with an empty string as value will return "1". Time
* complexity: O(1)
* @param key
* @return Boolean reply, true if the key exists, otherwise false
*/
public Boolean exists(final String key) {
checkIsInMultiOrPipeline();
client.exists(key);
return client.getIntegerReply() == 1;
}
/**
* Remove the specified keys. If a given key does not exist no operation is performed for this
* key. The command returns the number of keys removed. Time complexity: O(1)
* @param keys
* @return Integer reply, specifically: an integer greater than 0 if one or more keys were removed
* 0 if none of the specified key existed
*/
public Long del(final String... keys) {
checkIsInMultiOrPipeline();
client.del(keys);
return client.getIntegerReply();
}
public Long del(String key) {
client.del(key);
return client.getIntegerReply();
}
/**
* Return the type of the value stored at key in form of a string. The type can be one of "none",
* "string", "list", "set". "none" is returned if the key does not exist. Time complexity: O(1)
* @param key
* @return Status code reply, specifically: "none" if the key does not exist "string" if the key
* contains a String value "list" if the key contains a List value "set" if the key
* contains a Set value "zset" if the key contains a Sorted Set value "hash" if the key
* contains a Hash value
*/
public String type(final String key) {
checkIsInMultiOrPipeline();
client.type(key);
return client.getStatusCodeReply();
}
/**
* Returns all the keys matching the glob-style pattern as space separated strings. For example if
* you have in the database the keys "foo" and "foobar" the command "KEYS foo*" will return
* "foo foobar".
* <p>
* Note that while the time complexity for this operation is O(n) the constant times are pretty
* low. For example Redis running on an entry level laptop can scan a 1 million keys database in
* 40 milliseconds. <b>Still it's better to consider this one of the slow commands that may ruin
* the DB performance if not used with care.</b>
* <p>
* In other words this command is intended only for debugging and special operations like creating
* a script to change the DB schema. Don't use it in your normal code. Use Redis Sets in order to
* group together a subset of objects.
* <p>
* Glob style patterns examples:
* <ul>
* <li>h?llo will match hello hallo hhllo
* <li>h*llo will match hllo heeeello
* <li>h[ae]llo will match hello and hallo, but not hillo
* </ul>
* <p>
* Use \ to escape special chars if you want to match them verbatim.
* <p>
* Time complexity: O(n) (with n being the number of keys in the DB, and assuming keys and pattern
* of limited length)
* @param pattern
* @return Multi bulk reply
*/
public Set<String> keys(final String pattern) {
checkIsInMultiOrPipeline();
client.keys(pattern);
return BuilderFactory.STRING_SET.build(client.getBinaryMultiBulkReply());
}
/**
* Return a randomly selected key from the currently selected DB.
* <p>
* Time complexity: O(1)
* @return Singe line reply, specifically the randomly selected key or an empty string is the
* database is empty
*/
public String randomKey() {
checkIsInMultiOrPipeline();
client.randomKey();
return client.getBulkReply();
}
/**
* Atomically renames the key oldkey to newkey. If the source and destination name are the same an
* error is returned. If newkey already exists it is overwritten.
* <p>
* Time complexity: O(1)
* @param oldkey
* @param newkey
* @return Status code repy
*/
public String rename(final String oldkey, final String newkey) {
checkIsInMultiOrPipeline();
client.rename(oldkey, newkey);
return client.getStatusCodeReply();
}
/**
* Rename oldkey into newkey but fails if the destination key newkey already exists.
* <p>
* Time complexity: O(1)
* @param oldkey
* @param newkey
* @return Integer reply, specifically: 1 if the key was renamed 0 if the target key already exist
*/
public Long renamenx(final String oldkey, final String newkey) {
checkIsInMultiOrPipeline();
client.renamenx(oldkey, newkey);
return client.getIntegerReply();
}
/**
* Set a timeout on the specified key. After the timeout the key will be automatically deleted by
* the server. A key with an associated timeout is said to be volatile in Redis terminology.
* <p>
* Voltile keys are stored on disk like the other keys, the timeout is persistent too like all the
* other aspects of the dataset. Saving a dataset containing expires and stopping the server does
* not stop the flow of time as Redis stores on disk the time when the key will no longer be
* available as Unix time, and not the remaining seconds.
* <p>
* Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire
* set. It is also possible to undo the expire at all turning the key into a normal key using the
* {@link #persist(String) PERSIST} command.
* <p>
* Time complexity: O(1)
* @see <a href="http://code.google.com/p/redis/wiki/ExpireCommand">ExpireCommand</a>
* @param key
* @param seconds
* @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since
* the key already has an associated timeout (this may happen only in Redis versions <
* 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist.
*/
public Long expire(final String key, final int seconds) {
checkIsInMultiOrPipeline();
client.expire(key, seconds);
return client.getIntegerReply();
}
/**
* EXPIREAT works exctly like {@link #expire(String, int) EXPIRE} but instead to get the number of
* seconds representing the Time To Live of the key as a second argument (that is a relative way
* of specifing the TTL), it takes an absolute one in the form of a UNIX timestamp (Number of
* seconds elapsed since 1 Gen 1970).
* <p>
* EXPIREAT was introduced in order to implement the Append Only File persistence mode so that
* EXPIRE commands are automatically translated into EXPIREAT commands for the append only file.
* Of course EXPIREAT can also used by programmers that need a way to simply specify that a given
* key should expire at a given time in the future.
* <p>
* Since Redis 2.1.3 you can update the value of the timeout of a key already having an expire
* set. It is also possible to undo the expire at all turning the key into a normal key using the
* {@link #persist(String) PERSIST} command.
* <p>
* Time complexity: O(1)
* @see <a href="http://code.google.com/p/redis/wiki/ExpireCommand">ExpireCommand</a>
* @param key
* @param unixTime
* @return Integer reply, specifically: 1: the timeout was set. 0: the timeout was not set since
* the key already has an associated timeout (this may happen only in Redis versions <
* 2.1.3, Redis >= 2.1.3 will happily update the timeout), or the key does not exist.
*/
public Long expireAt(final String key, final long unixTime) {
checkIsInMultiOrPipeline();
client.expireAt(key, unixTime);
return client.getIntegerReply();
}
/**
* The TTL command returns the remaining time to live in seconds of a key that has an
* {@link #expire(String, int) EXPIRE} set. This introspection capability allows a Redis client to
* check how many seconds a given key will continue to be part of the dataset.
* @param key
* @return Integer reply, returns the remaining time to live in seconds of a key that has an
* EXPIRE. In Redis 2.6 or older, if the Key does not exists or does not have an
* associated expire, -1 is returned. In Redis 2.8 or newer, if the Key does not have an
* associated expire, -1 is returned or if the Key does not exists, -2 is returned.
*/
public Long ttl(final String key) {
checkIsInMultiOrPipeline();
client.ttl(key);
return client.getIntegerReply();
}
/**
* Move the specified key from the currently selected DB to the specified destination DB. Note
* that this command returns 1 only if the key was successfully moved, and 0 if the target key was
* already there or if the source key was not found at all, so it is possible to use MOVE as a
* locking primitive.
* @param key
* @param dbIndex
* @return Integer reply, specifically: 1 if the key was moved 0 if the key was not moved because
* already present on the target DB or was not found in the current DB.
*/
public Long move(final String key, final int dbIndex) {
checkIsInMultiOrPipeline();
client.move(key, dbIndex);
return client.getIntegerReply();
}
/**
* GETSET is an atomic set this value and return the old value command. Set key to the string
* value and return the old value stored at key. The string can't be longer than 1073741824 bytes
* (1 GB).
* <p>
* Time complexity: O(1)
* @param key
* @param value
* @return Bulk reply
*/
public String getSet(final String key, final String value) {
checkIsInMultiOrPipeline();
client.getSet(key, value);
return client.getBulkReply();
}
/**
* Get the values of all the specified keys. If one or more keys dont exist or is not of type
* String, a 'nil' value is returned instead of the value of the specified key, but the operation
* never fails.
* <p>
* Time complexity: O(1) for every key
* @param keys
* @return Multi bulk reply
*/
public List<String> mget(final String... keys) {
checkIsInMultiOrPipeline();
client.mget(keys);
return client.getMultiBulkReply();
}
/**
* SETNX works exactly like {@link #set(String, String) SET} with the only difference that if the
* key already exists no operation is performed. SETNX actually means "SET if Not eXists".
* <p>
* Time complexity: O(1)
* @param key
* @param value
* @return Integer reply, specifically: 1 if the key was set 0 if the key was not set
*/
public Long setnx(final String key, final String value) {
checkIsInMultiOrPipeline();
client.setnx(key, value);
return client.getIntegerReply();
}
/**
* The command is exactly equivalent to the following group of commands:
* {@link #set(String, String) SET} + {@link #expire(String, int) EXPIRE}. The operation is
* atomic.
* <p>
* Time complexity: O(1)
* @param key
* @param seconds
* @param value
* @return Status code reply
*/
public String setex(final String key, final int seconds, final String value) {
checkIsInMultiOrPipeline();
client.setex(key, seconds, value);
return client.getStatusCodeReply();
}
/**
* Set the the respective keys to the respective values. MSET will replace old values with new
* values, while {@link #msetnx(String...) MSETNX} will not perform any operation at all even if
* just a single key already exists.
* <p>
* Because of this semantic MSETNX can be used in order to set different keys representing
* different fields of an unique logic object in a way that ensures that either all the fields or
* none at all are set.
* <p>
* Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B
* are modified, another client talking to Redis can either see the changes to both A and B at
* once, or no modification at all.
* @see #msetnx(String...)
* @param keysvalues
* @return Status code reply Basically +OK as MSET can't fail
*/
public String mset(final String... keysvalues) {
checkIsInMultiOrPipeline();
client.mset(keysvalues);
return client.getStatusCodeReply();
}
/**
* Set the the respective keys to the respective values. {@link #mset(String...) MSET} will
* replace old values with new values, while MSETNX will not perform any operation at all even if
* just a single key already exists.
* <p>
* Because of this semantic MSETNX can be used in order to set different keys representing
* different fields of an unique logic object in a way that ensures that either all the fields or
* none at all are set.
* <p>
* Both MSET and MSETNX are atomic operations. This means that for instance if the keys A and B
* are modified, another client talking to Redis can either see the changes to both A and B at
* once, or no modification at all.
* @see #mset(String...)
* @param keysvalues
* @return Integer reply, specifically: 1 if the all the keys were set 0 if no key was set (at
* least one key already existed)
*/
public Long msetnx(final String... keysvalues) {
checkIsInMultiOrPipeline();
client.msetnx(keysvalues);
return client.getIntegerReply();
}
/**
* IDECRBY work just like {@link #decr(String) INCR} but instead to decrement by 1 the decrement
* is integer.
* <p>
* INCR commands are limited to 64 bit signed integers.
* <p>
* Note: this is actually a string operation, that is, in Redis there are not "integer" types.
* Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
* and then converted back as a string.
* <p>
* Time complexity: O(1)
* @see #incr(String)
* @see #decr(String)
* @see #incrBy(String, long)
* @param key
* @param integer
* @return Integer reply, this commands will reply with the new value of key after the increment.
*/
public Long decrBy(final String key, final long integer) {
checkIsInMultiOrPipeline();
client.decrBy(key, integer);
return client.getIntegerReply();
}
/**
* Decrement the number stored at key by one. If the key does not exist or contains a value of a
* wrong type, set the key to the value of "0" before to perform the decrement operation.
* <p>
* INCR commands are limited to 64 bit signed integers.
* <p>
* Note: this is actually a string operation, that is, in Redis there are not "integer" types.
* Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
* and then converted back as a string.
* <p>
* Time complexity: O(1)
* @see #incr(String)
* @see #incrBy(String, long)
* @see #decrBy(String, long)
* @param key
* @return Integer reply, this commands will reply with the new value of key after the increment.
*/
public Long decr(final String key) {
checkIsInMultiOrPipeline();
client.decr(key);
return client.getIntegerReply();
}
/**
* INCRBY work just like {@link #incr(String) INCR} but instead to increment by 1 the increment is
* integer.
* <p>
* INCR commands are limited to 64 bit signed integers.
* <p>
* Note: this is actually a string operation, that is, in Redis there are not "integer" types.
* Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
* and then converted back as a string.
* <p>
* Time complexity: O(1)
* @see #incr(String)
* @see #decr(String)
* @see #decrBy(String, long)
* @param key
* @param integer
* @return Integer reply, this commands will reply with the new value of key after the increment.
*/
public Long incrBy(final String key, final long integer) {
checkIsInMultiOrPipeline();
client.incrBy(key, integer);
return client.getIntegerReply();
}
/**
* INCRBYFLOAT
* <p>
* INCRBYFLOAT commands are limited to double precision floating point values.
* <p>
* Note: this is actually a string operation, that is, in Redis there are not "double" types.
* Simply the string stored at the key is parsed as a base double precision floating point value,
* incremented, and then converted back as a string. There is no DECRYBYFLOAT but providing a
* negative value will work as expected.
* <p>
* Time complexity: O(1)
* @param key
* @param value
* @return Double reply, this commands will reply with the new value of key after the increment.
*/
public Double incrByFloat(final String key, final double value) {
checkIsInMultiOrPipeline();
client.incrByFloat(key, value);
String dval = client.getBulkReply();
return (dval != null ? new Double(dval) : null);
}
/**
* Increment the number stored at key by one. If the key does not exist or contains a value of a
降Redis里Key值增加 1;如果key不存在或者是错误类型,都是从 0 开始计数
* wrong type, set the key to the value of "0" before to perform the increment operation.
* <p>
* INCR commands are limited to 64 bit signed integers.
此命令都是以64 字符存储
* <p>
* Note: this is actually a string operation, that is, in Redis there are not "integer" types.
* Simply the string stored at the key is parsed as a base 10 64 bit signed integer, incremented,
* and then converted back as a string.
* <p>
* Time complexity: O(1)
* @see #incrBy(String, long)
* @see #decr(String)
* @see #decrBy(String, long)
* @param key
* @return Integer reply, this commands will reply with the new value of key after the increment.
*/
public Long incr(final String key) {
checkIsInMultiOrPipeline();
client.incr(key);
return client.getIntegerReply();
}
/**
* If the key already exists and is a string, this command appends the provided value at the end
* of the string. If the key does not exist it is created and set as an empty string, so APPEND
* will be very similar to SET in this special case.
* <p>
* Time complexity: O(1). The amortized time complexity is O(1) assuming the appended value is
* small and the already present value is of any size, since the dynamic string library used by
* Redis will double the free space available on every reallocation.
* @param key
* @param value
* @return Integer reply, specifically the total length of the string after the append operation.
*/
public Long append(final String key, final String value) {
checkIsInMultiOrPipeline();
client.append(key, value);
return client.getIntegerReply();
}
/**
* Return a subset of the string from offset start to offset end (both offsets are inclusive).
* Negative offsets can be used in order to provide an offset starting from the end of the string.
* So -1 means the last char, -2 the penultimate and so forth.
* <p>
* The function handles out of range requests without raising an error, but just limiting the
* resulting range to the actual length of the string.
* <p>
* Time complexity: O(start+n) (with start being the start index and n the total length of the
* requested range). Note that the lookup part of this command is O(1) so for small strings this
* is actually an O(1) command.
* @param key
* @param start
* @param end
* @return Bulk reply
*/
public String substr(final String key, final int start, final int end) {
checkIsInMultiOrPipeline();
client.substr(key, start, end);
return client.getBulkReply();
}
/**
* Set the specified hash field to the specified value.
* <p>
* If key does not exist, a new key holding a hash is created.
* <p>
* <b>Time complexity:</b> O(1)
* @param key
* @param field
* @param value
* @return If the field already exists, and the HSET just produced an update of the value, 0 is
* returned, otherwise if a new field is created 1 is returned.
*/
public Long hset(final String key, final String field, final String value) {
checkIsInMultiOrPipeline();
client.hset(key, field, value);
return client.getIntegerReply();
}
/**
* If key holds a hash, retrieve the value associated to the specified field.
* <p>
* If the field is not found or the key does not exist, a special 'nil' value is returned.
* <p>
* <b>Time complexity:</b> O(1)
* @param key
* @param field
* @return Bulk reply
*/
public String hget(final String key, final String field) {
checkIsInMultiOrPipeline();
client.hget(key, field);
return client.getBulkReply();
}
/**
* Set the specified hash field to the specified value if the field not exists. <b>Time
* complexity:</b> O(1)
* @param key
* @param field
* @param value
* @return If the field already exists, 0 is returned, otherwise if a new field is created 1 is
* returned.
*/
public Long hsetnx(final String key, final String field, final String value) {
checkIsInMultiOrPipeline();
clien