Home  >  Article  >  Java  >  Redis Java connection method

Redis Java connection method

WBOY
WBOYforward
2023-05-04 14:52:061304browse

1. Java connection pool connection (pipeline, lua)

Add the following dependencies

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency>

1, Test

public class Test {public static void main(String[] args) {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(20);jedisPoolConfig.setMaxIdle(10);jedisPoolConfig.setMinIdle(5);// timeout,这里既是连接超时又是读写超时,从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.157.6", 6379, 3000, null);Jedis jedis = null;try {// 从redis连接池里拿出一个连接执行命令jedis = jedisPool.getResource();System.out.println(jedis.set("single", "zhuge"));System.out.println(jedis.get("single"));// 管道示例// 管道的命令执行方式:cat redis.txt | redis‐cli ‐h 127.0.0.1 ‐a password ‐ p 6379 ‐‐pipePipeline pl = jedis.pipelined();for (int i = 0; i < 10; i++) {pl.incr("pipelineKey");pl.set("zhuge" + i, "zhuge");}List<Object> results = pl.syncAndReturnAll();System.out.println(results);// lua脚本模拟一个商品减库存的原子操作// lua脚本命令执行方式:redis‐cli ‐‐eval /tmp/test.lua , 10jedis.set("product_count_10016", "15"); // 初始化商品10016的库存String script = " local count = redis.call('get', KEYS[1]) " +" local a = tonumber(count) "+" local b = tonumber(ARGV[1]) " +" if a >= b then " +"  redis.call('set', KEYS[1], count‐b) "+"  return 1 " +" end " +" return 0 ";System.out.println("script:"+script);Object obj = jedis.eval(script, Arrays.asList("product_count_10016"), Arrays.asList("10"));System.out.println(obj);} catch (Exception e) {e.printStackTrace();} finally {// 注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。if (jedis != null)jedis.close();}}}

2, Pipeline (Pipeline)

The client can send multiple requests at one time without waiting for the server's response. After all commands have been sent, it can read the service response at once. This can greatly reduce the network transmission overhead of multiple command execution, pipeline The network overhead of executing multiple commands is actually only equivalent to the network overhead of executing one command. It should be noted that commands are packaged and sent in pipeline mode, and redis must cache the processing results of all commands before processing them. The more commands you package, the more memory the cache consumes. So it’s not that the more commands you package, the better. Each command sent in the pipeline will be executed immediately by the server. If the execution fails, the information will be obtained in the subsequent response; that is, the pipeline does not express the semantics of "all commands succeed together". The previous command in the pipeline fails, and the following command fails. The command will have no effect and will continue to be executed.

See the example above.

3. Redis Lua script

Redis launched the script function in 2.6, allowing developers to use Lua language to write scripts and pass them to Redis for execution. The benefits of using scripts are as follows:

1. Reduce network overhead

The original five network request operations can be completed with one request, and the logic of the original five requests is completed on the redis server. Using scripts reduces network round-trip latency. This is similar to pipes.

2. Atomic operation

Redis will execute the entire script as a whole, and no other commands will be inserted in the middle. Pipes are not atomic, but redis batch operation commands (similar to mset) are atomic.

3. Replace the transaction function of redis

The transaction function of redis is very useless and does not support rollback when reporting errors. However, the Lua script of redis almost has regular transaction functions and supports error reporting. For roll operations, it is officially recommended that if you want to use the transaction function of redis, you can use redis lua instead.
There is this passage in the official website documentation:

A Redis script is transactional by definition, so everything you can do with a Redis transaction, you can also do with a script, and usually the script will be both simpler and faster.

Starting from Redis2.6.0 version, through the built-in Lua interpreter, you can use the EVAL command to evaluate Lua scripts. The format
of the EVAL command is as follows:

EVAL script numkeys key [key ...] arg [arg ...]

The script parameter is a Lua script program, which will be run in the Redis server context. This script does not (and should not) be defined as a
Lua function. The numkeys parameter is used to specify the number of key parameters. The key parameter key [key ...] starts from the third parameter of EVAL and represents the Redis keys (keys) used in the script. These key parameters can be passed through the global variable KEYS array in Lua. Use 1
as the base address to access (KEYS[1], KEYS[2], and so on). At the end of the command, those additional parameters arg [arg...] that are not key parameters can be accessed in Lua through the global variable ARGV array. The access form is similar to the KEYS variable (ARGV[1], ARGV[2], and so on) . For example

127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second2 1) "key1"3 2) "key2"4 3) "first"5 4) "second"
where "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" is the Lua script being evaluated, and the number 2 specifies the number of key parameters.

Amount, key1 and key2 are key parameters, accessed using KEYS[1] and KEYS[2] respectively, and the last first and second are additional
parameters, which can be accessed through ARGV[1] and ARGV[2 ] access them. In Lua scripts, you can use the redis.call() function to execute Redis commands

For examples, refer to the above.

Be careful not to have infinite loops or time-consuming operations in Lua scripts, otherwise redis will block and will not accept other commands. Therefore, when using

, be careful not to have infinite loops or time-consuming operations. Operation. redis is a single-process, single-thread execution script. Pipes do not block redis.

2. Sentinel’s Jedis connection code

public class Test2 {public static void main(String[] args) {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(20);jedisPoolConfig.setMaxIdle(10);jedisPoolConfig.setMinIdle(5);String masterName = "mymaster";Set<String> sentinels = new HashSet<String>();sentinels.add(new HostAndPort("192.168.157.6",26379).toString());sentinels.add(new HostAndPort("192.168.157.6",26380).toString());sentinels.add(new HostAndPort("192.168.157.6",26381).toString());// timeout,这里既是连接超时又是读写超时,从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, jedisPoolConfig, 3000, null);Jedis jedis = null;try {// 从redis连接池里拿出一个连接执行命令jedis = jedisSentinelPool.getResource();while(true) {Thread.sleep(1000);try {System.out.println(jedis.set("single", "zhuge"));System.out.println(jedis.get("single"));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}} catch (Exception e) {e.printStackTrace();} finally {// 注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。if (jedis != null)jedis.close();}}}

3. Sentinel’s Spring Boot integrated Redis connection

1. Introducing related dependencies

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring‐boot‐starter‐data‐redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons‐pool2</artifactId></dependency>

2. springboot Project core configuration

server:port: 8080spring:redis:database: 0timeout: 3000sentinel: #哨兵模式master: mymaster #主服务器所在集群名称nodes: 192.168.0.60:26379,192.168.0.60:26380,192.168.0.60:26381lettuce:pool:max‐idle: 50min‐idle: 10max‐active: 100max‐wait: 1000

3, access code

@RestControllerpublic class IndexController {private static final Logger logger = LoggerFactory.getLogger(IndexController.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 测试节点挂了哨兵重新选举新的master节点,客户端是否能动态感知到* 新的master选举出来后,哨兵会把消息发布出去,客户端实际上是实现了一个消息监听机制,* 当哨兵把新master的消息发布出去,客户端会立马感知到新master的信息,从而动态切换访问的masterip* @throws InterruptedException*/@RequestMapping("/test_sentinel")public void testSentinel() throws InterruptedException {int i = 1;while (true){try {stringRedisTemplate.opsForValue().set("zhuge"+i, i+"");System.out.println("设置key:"+ "zhuge" + i);i++;Thread.sleep(1000);}catch (Exception e){logger.error("错误:", e);}}}}

4, StringRedisTemplate and RedisTemplate

spring encapsulates the RedisTemplate object to perform various operations on redis, and it supports all redis native API.

RedisTemplate provides the use of several commonly used interface methods, namely:

private ValueOperations<K, V> valueOps;private HashOperations<K, V> hashOps;private ListOperations<K, V> listOps;private SetOperations<K, V> setOps;private ZSetOperations<K, V> zSetOps;
RedisTemplate defines operations on 5 data structures

redisTemplate.opsForValue();//操作字符串redisTemplate.opsForHash();//操作hashredisTemplate.opsForList();//操作listredisTemplate.opsForSet();//操作setredisTemplate.opsForZSet();//操作有序set
StringRedisTemplate inherits from RedisTemplate, also The same operations as above are available.

StringRedisTemplate uses the String serialization strategy by default, and the saved keys and values ​​are serialized and saved
using this strategy. RedisTemplate uses the JDK's serialization strategy by default, and the saved keys and values ​​are serialized and saved using this strategy.
That is, if the content is saved with RedisTemplate, you will see a lot of encoded characters when you open it in the console, which is difficult to understand.

Redis客户端命令对应的RedisTemplate中的方法列表:
Redis Java连接的方法
Redis Java连接的方法
Redis Java连接的方法
Redis Java连接的方法

四、集群的Jedis连接代码

public class Test3 {public static void main(String[] args) throws IOException {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(20);jedisPoolConfig.setMaxIdle(10);jedisPoolConfig.setMinIdle(5);Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();jedisClusterNode.add(new HostAndPort("192.168.0.61", 8001));jedisClusterNode.add(new HostAndPort("192.168.0.62", 8002));jedisClusterNode.add(new HostAndPort("192.168.0.63", 8003));jedisClusterNode.add(new HostAndPort("192.168.0.61", 8004));jedisClusterNode.add(new HostAndPort("192.168.0.62", 8005));jedisClusterNode.add(new HostAndPort("192.168.0.63", 8006));// timeout,这里既是连接超时又是读写超时,从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数JedisCluster jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "zhuge", jedisPoolConfig);try {while(true) {Thread.sleep(1000);try {System.out.println(jedisCluster.set("single", "zhuge"));System.out.println(jedisCluster.get("single"));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}} catch (Exception e) {e.printStackTrace();} finally {// 注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。if (jedisCluster != null)jedisCluster.close();}}}

五、集群模式Springboot整合redis

其实集群模式跟哨兵模式很类似,只不过配置文件修改一下即可

server:port: 8080spring:redis:database: 0timeout: 3000password: zhugecluster:nodes:192.168.0.61:8001,192.168.0.62:8002,192.168.0.63:8003lettuce:pool:# 连接池中的最大空闲连接max‐idle: 50# 连接池中最小空闲连接min‐idle: 10max‐active: 100# 连接池阻塞等待时间(负值表示没有限制)max‐wait: 1000

只不过 sentinel换成了 cluster,然后API什么的都是一样的。

The above is the detailed content of Redis Java connection method. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete