Jedis连接Redis:

非线程安全

如果是多线程环境下共用一个Jedis连接池,会产生线程安全问题,可以通过创建多个Jedis实例来解决,但是创建许多socket会影响性能,因此好一点的方法是使用JedisPool

https://blog.csdn.net/lihao21/article/details/46830553

https://www.jianshu.com/p/5e4a1f92c88f

为什么 jedis不是线程安全的,可以通过一个demo来说明:

public class BadConcurrentJedisTest {

    private static final ExecutorService pool = Executors.newFixedThreadPool(20);

    private static final Jedis jedis = new Jedis("127.0.0.1", 6379);

    public static void main(String[] args) {
for(int i=0;i<20;i++){
pool.execute(new RedisSet());
}
} static class RedisSet implements Runnable{ @Override
public void run() {
while(true){
jedis.set("hello", "world");
}
} }

这时候后台报错:

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Socket Closed

主要的原因就在于jedis实例中的两个成员变量:RedisInputStream和RedisOutputStream

jedis在执行每一个命令之前都会先执行connect方法,socket是一个共享变量,在多线程的情况下可能存在:线程1执行到:

outputStream = new RedisOutputStream(socket.getOutputStream());
inputStream = new RedisInputStream(socket.getInputStream());

线程2执行到:

socket = new Socket();
socket.connect(new InetSocketAddress(host, port), connectionTimeout);
因为线程2重新初始化了socket但是还没有执行connect,所以线程1执行socket.getOutputStream()或者socket.getInputStream()就会抛出java.net.SocketException: Socket is not connected。

Jedis解决线程安全的方式就是使用连接池:

每个线程去连接池中获取一个Jedis实例,这样就在有限个socket的情况下保证了线程安全

Lettuce连接Redis:

线程安全

Lettuce是基于netty的,性能比较好。

多线程使用同一连接实例时,是线程安全的。

application-test.yml

redis:
nodes:
- host1:port1
- host2:port2

-----------------------------------------------------------------Lettuce-----------------------------------------------------------------

导入依赖:

    //Redis
compile 'org.springframework.boot:spring-boot-starter-data-redis-reactive'

配置类:

import io.lettuce.core.RedisURI;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.ArrayList;
import java.util.List; @Configuration
@ConfigurationProperties(prefix = "redis")
public class LettuceConfig {
private List<String> nodes; public List<String> getNodes() {
return nodes;
} public void setNodes(List<String> nodes) {
this.nodes = nodes;
} @Bean
RedisClusterCommands<String, String> redisCommands() {
List<RedisURI> uriList = new ArrayList<>();
nodes.forEach(node -> {
String[] addrStr = node.split(":");
String host = addrStr[0];
int port = Integer.parseInt(addrStr[1]); RedisURI redisUri = RedisURI.Builder.redis(host).withPort(port).build();
uriList.add(redisUri);
});
RedisClusterClient redisClient = RedisClusterClient.create(uriList);
StatefulRedisClusterConnection<String, String> connection = redisClient.connect();
RedisClusterCommands<String, String> syncCommands = connection.sync(); return syncCommands;
} }

-----------------------------------------------------------------Jedis-----------------------------------------------------------------

导入依赖:

compile group: 'redis.clients', name: 'jedis', version: '2.9.0'

配置类:

package com.youdao.outfox.interflow.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster; import java.util.HashSet;
import java.util.List;
import java.util.Set; @Configuration
@ConfigurationProperties(prefix = "redis")
public class JedisClusterConfig { private List<String> nodes; public List<String> getNodes() {
return nodes;
} public void setNodes(List<String> nodes) {
this.nodes = nodes;
} @Bean
public JedisCluster jedisCluster() {
Set<HostAndPort> jedisClusterNodes = new HashSet<>();
nodes.forEach(node -> {
String[] addrStr = node.split(":");
String host = addrStr[0];
int port = Integer.parseInt(addrStr[1]);
jedisClusterNodes.add(new HostAndPort(host, port));
});
return new JedisCluster(jedisClusterNodes, 5, 2);
}
}

--------------------------------更新-------------------------------------

Redis——SpringBoot项目使用Lettuce和Jedis接入Redis集群的更多相关文章

  1. redis在项目中的使用(单机版、集群版)

    1.下载jar包:jedis-2.6.2.jar 2.代码: JedisDao.java: package com.test.www.dao; public interface JedisDao { ...

  2. Redis(七):Jedis简介和集群

    Jedis简介 1.Jedis 是Redis 客户端工具jar2.使用非集群版示例代码 Jedis jedis = new Jedis("192.168.139.132", 637 ...

  3. redis在Windows下以后台服务一键搭建集群(多机器)

    redis在Windows下以后台服务一键搭建集群(多机器) 一.概述 此教程介绍如何在windows系统中多台机器之间布置redis集群,同时要以后台服务的模式运行.布置以脚本的形式,一键完成.多台 ...

  4. redis在Windows下以后台服务一键搭建集群(单机--伪集群)

    redis在Windows下以后台服务一键搭建集群(单机--伪集群) 一.概述 此教程介绍如何在windows系统中同一台机器上布置redis伪集群,同时要以后台服务的模式运行.布置以脚本的形式,一键 ...

  5. Redis三种模式——主从复制,哨兵模式,集群

    一.Redis主从复制作用 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复:实际上是一种服务的冗余. 负 ...

  6. Docker Compose搭建Redis一主二从三哨兵高可用集群

    一.Docker Compose介绍 https://docs.docker.com/compose/ Docker官方的网站是这样介绍Docker Compose的: Compose是用于定义和运行 ...

  7. redis 在windows 上面的安装和使用,集群搭建

    redis作为nosql数据库,将数据存储到内存中(缓存),具有非常高的性能.下面讲解一下redis的安装及java api的使用. 1:redis 安装 windows 上面直接下载msi文件,安装 ...

  8. SpringBoot中使用消息中间件Kafka实现Websocket的集群

    1.在实际项目中,由于数据量的增大及并发数的增多,我们不可能只用一台Websocket服务,这个时候就需要用到Webscoket的集群.但是Websocket集群会遇到一些问题.首先我们肯定会想到直接 ...

  9. jedis:分片集群使用

    jedis使用 引入依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis ...

随机推荐

  1. 《0day安全-软件漏洞分析技术》实验笔记1

    Crack 小实验 工具 Dev C++(书上使用的VS) IDA_Pro_v7.0 Ollydbg LordPE 010 editor 使用IDA打开文件 找到程序分支点 空格跳转到汇编界面 得到V ...

  2. 【miscellaneous】硬解码与软解码

    在显卡技术日益成熟的今天,一些概念我们都不是很清楚了,那么显卡硬件解码功能是什么意思呢?高清硬解和软件有什么不同呢?显卡配置需不需要考虑硬件解码呢?电脑爱好者为您分析. 什么是硬件解码? 显卡硬件解码 ...

  3. mysql——修改表名、修改字段名、修改字段数据类型、增加字段、删除字段、修改字段排列位置、修改存储引擎、删除表 (示例)

    一.创建表和插入数据: ), mz ), bz ) ); ,'sww','sww01'); ,'aww','aww02'); ,'qww','qww03'), (,'eww','eww04'), (, ...

  4. ubantu

    1.win10 到Microsoft store 下载ubantu,并安装 2.开启SSH服务,需要开启openssh-server 删除ssh:sudo apt-get remove --purge ...

  5. [c++] 用宏定义一个函数

    要点:变量都用括号括起来,防止出错,结尾不需要;.在实际编程中,不推荐把复杂的函数使用宏,不容易调试.多行用\ 要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和 ...

  6. java 实现读取某个目录下指定类型的文件

    我这里是读取txt类型的文件,在指定的目录下有不同类型的文件 实现代码,读取txt类型的文件并打印出该文件的绝对路径 package com.SBgong.test; import java.io.F ...

  7. Linux动态链接之GOT与PLT

    转载于:http://www.cnblogs.com/xingyun/archive/2011/12/10/2283149.html   我们知道函数名就是一个内存地址,这个地址指向函数的入口.调用函 ...

  8. dual Oracle兼容

    CREATE OR REPLACE VIEW dual ASSELECT NULL::"unknown"WHERE 1 = 1;

  9. Android开发build出现java.lang.NumberFormatException: For input string: "tle 0x7f0800aa"错误的解决方案

    查看异常栈没有发现项目代码的问题,因为问题是出现在layout文件中. 全局查找tle这个,发现在某个layout文件中title一词被变成ti tle了,结果Android就xjb报错了. 参考

  10. 矩阵快速幂(Matrix_Fast_Power)

    一.基础知识(1)矩阵乘法 https://blog.csdn.net/weixin_43272781/article/details/82899737 简单的说矩阵就是二维数组,数存在里面,矩阵乘法 ...