在windows上搭建redis集群,结合springboot 2.x配置lettuce及redisson

一、redis集群介绍

Redis cluster(redis集群)是在版本3.0后才支持的架构,和其他集群一样,都是为了解决单台服务器不够用的情况,也防止了主服务器宕机无备用服务器,多个节点网络互联数据共享,所有节点都是一主一从(也可以一主多从),其中不提供服务,只做为备份。

二、所需软件环境

1、下载redis最新版本(版本必需要3.0以上)

2、下载地址: https://github.com/MSOpenTech/redis/releases 下载 Redis-x64-3.2.100.zip

3、安装Ruby语言运行环境,建议下载2.3或以上,2.2版本过低影响后续操作
http://dl.bintray.com/oneclick/rubyinstaller/rubyinstaller-2.2.4-x64.exe
https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
在这里插入图片描述
选中3个,然后点击安装

安装好后会弹出一个黑色窗体,也可以选择redis安装目录,然后对Ruby进行配置,执行

gem install redis

如果执行失败,或者下载较慢可切换国内镜像:

切换国内镜像命令:

gem sources --add http://gems.ruby-china.org/  --remove https://rubygems.org/

如果开发环境是内网,没有外网访问权限时,也可以下载离线安装包

https://rubygems.org/,输入对应的gem名字进行下载(选好版本点右下角下载按钮)

下载完毕之后可以直接放在ruby安装的目录
在这里插入图片描述
然后在安装的目录执行指令(例如redis):

gem install ./redis-3.2.1.gem –local

即可。
在这里插入图片描述安装完毕即可关闭窗体。

三、开始搭建redis集群

3.1、将第二步下载的Redis-x64-3.2.100.zip解压,并且复制五份,分别命名7000-7005

在这里插入图片描述

3.2、 修改6个文件夹下redis.windows.conf,修改port分别为7000-7005

在这里插入图片描述

3.3、 修改其他配置支持集群
cluster-enabled yes

cluster-config-file nodes-7000.conf 

cluster-node-timeout 15000

appendonly yes

如果cluster-enabled 不为yes, 那么在使用JedisCluster集群代码获取的时候,会报错。

cluster-node-timeout 调整为 15000,那么在创建集群的时候,不会超时。

cluster-config-file nodes-7000.conf 是为该节点的配置信息,这里使用 nodes-端口.conf命名方法。服务启动后会在目录生成该文件。

appendonly 持久化配置,默认no,也可不更改

在这里插入图片描述
记得把其他节点配置也要改

3.4、 编写一个startup.bat来启动redis,在每个节点目录下创建start.bat,内容如下(端口记得对应):
title redis-7000
redis-server.exe redis.windows.conf
3.5、 安装集群脚本redis-trib,安装到redis目录下(7000目录下)

下载地址 https://raw.githubusercontent.com/antirez/redis/unstable/src/redis-trib.rb

如果失效可访问:https://github.com/beebol/redis-trib.rb

3.6、 启动每个节点并且执行集群构建脚本

把每个节点下的 startup.bat双击启动, 再切换到redis目录在命令行中执行

ruby redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 

备注:有朋友反应上面的语句执行不成功。可以在前面加上ruby再运行。

–replicas 1 表示每个主数据库拥有从数据库个数为1。master节点不能少于3个,所以我们用了6个redis

在这里插入图片描述
在出现 Can I set the above configuration? (type ‘yes’ to accept): 请确定并输入 yes 。成功后的结果如下:
在这里插入图片描述

3.7、 测试

使用Redis客户端Redis-cli.exe来查看数据记录数,以及集群相关信息

命令 redis-cli –c –h ”地址” –p “端口号” ; c 表示集群
在这里插入图片描述
输入dbsize查询 记录总数
在这里插入图片描述
输入cluster info可以从客户端的查看集群的信息
在这里插入图片描述

注意:如果出现创建集群不成功:

dos命令窗口执行创建集群命令,出现以下提示:

E:\redis\cluster>redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
WARNING: redis-trib.rb is not longer available!
You should use redis-cli instead.

All commands and features belonging to redis-trib.rb have been moved
to redis-cli.
In order to use them you should call redis-cli with the --cluster
option followed by the subcommand name, arguments and options.

Use the following syntax:
redis-cli --cluster SUBCOMMAND [ARGUMENTS] [OPTIONS]

Example:
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

To get help about all subcommands, type:
redis-cli --cluster help

原因是redis-trib.rb的链接指向官网最新的版本。从对应版本(redis3.2.0即可)的源码压缩包中src文件夹下找

到对应的redis-trib.rb文件使用,即可解决问题。

下载redis源码版压缩包:http://download.redis.io/releases/

至此,redis集群搭建成功,可在项目中测试redis集群。

四、spring boot 2.x整合redis集群配置lettuce

4.1、 pom.xml 配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.xu</groupId>
  <artifactId>testboot</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  
  <parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.1.RELEASE</version>
 </parent>

  <name>testboot</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
  
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <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>
    
  </dependencies>
</project>

本文使用到lettuce,commons-pool2必不可少。

4.2、YML 配置(注意:nodes可以配置单个或多个主或从节点)
server:
  port: 8088
  
  
spring:
   redis:
    timeout: 6000ms
    password: 
    cluster:
      max-redirects: 3  # 获取失败 最大重定向次数 
      nodes:
        - 127.0.0.1:7000
        - 127.0.0.1:7001
        - 127.0.0.1:7002
        - 127.0.0.1:7003
        - 127.0.0.1:7004
        - 127.0.0.1:7005 
    lettuce:
      pool:
        max-active: 1000  #连接池最大连接数(使用负值表示没有限制)
        max-idle: 10 # 连接池中的最大空闲连接
        min-idle: 5 # 连接池中的最小空闲连接
        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
4.3、 新建RedisConfig,连接池注入配置信息
package com.xu.testboot.config;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
	
	 @Bean
	    public RedisTemplate<String, Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
	        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
	        template.setKeySerializer(new StringRedisSerializer());
	        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
	        template.setConnectionFactory(redisConnectionFactory);
	        return template;
	    }
}

在使用的地方直接注入即可

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private StringRedisTemplate redisTemplate;

五、 其他redis配置方式

5.1、不指定redis连接池

#系统默认连接池

yml配置文件:

spring:
  redis:
    cluster:
      nodes:
        - 127.0.0.1:7000
        - 127.0.0.1:7001
        - 127.0.0.1:7002
        - 127.0.0.1:7003
        - 127.0.0.1:7004
        - 127.0.0.1:7005 
      max-redirects: 3  # 获取失败 最大重定向次数
    pool:
      max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
      max-idle: 10    # 连接池中的最大空闲连接
      max-wait: -1   # 连接池最大阻塞等待时间(使用负值表示没有限制)
      min-idle:  5     # 连接池中的最小空闲连接
    timeout: 6000  # 连接超时时长(毫秒)  

这种方式 redisTemplate 可直接使用默认,在使用的地方直接注入即可

@Autowired
private RedisTemplate<String, Object> redisTemplate;
5.2、 使用jedis连接池

#使用jedis连接池

yml配置文件:

spring:
  redis:
    password:    # 密码(默认为空)
    timeout: 6000ms  # 连接超时时长(毫秒)
    cluster:
      nodes:
        - 127.0.0.1:7000
        - 127.0.0.1:7001
        - 127.0.0.1:7002
        - 127.0.0.1:7003
        - 127.0.0.1:7004
        - 127.0.0.1:7005 
    jedis:
      pool:
        max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 10      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

//连接池注入配置信息

@Configuration
public class RedisConfig {
   @Autowired
   private RedisConnectionFactory factory;
 
   @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }
}

同样在使用的地方直接注入即可

@Autowired
private RedisTemplate<String, Object> redisTemplate;

六、 其他插件配置redisson(redis集群)

6.1、首先配置pom.xml
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.5.0</version>
</dependency>
6.2、创建 redisson配置类RedissonManager
package com.xu.testboot.config;

import java.io.IOException;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

/**
 * redisson配置
 */
@Configuration
public class RedissonManager {

	@Value("${spring.redis.cluster.nodes}")
	private String cluster;

	@Value("${spring.redis.password}")
	private String password;

	@Bean
	public RedissonClient getRedisson() throws IOException {
		String[] nodes = cluster.split(",");
		// redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加
		for (int i = 0; i < nodes.length; i++) {
			nodes[i] = "redis://" + nodes[i];
		}
		RedissonClient redisson = null;
		Config config = new Config();
		ClusterServersConfig clusterConfig = config.useClusterServers() // 这是用的集群server
				.setScanInterval(2000) // 设置集群状态扫描时间
				.addNodeAddress(nodes);
		if (StringUtils.isEmpty(password) == false) {
			clusterConfig.setPassword(password);
		}
		redisson = Redisson.create(config);
		// 可通过打印来检测是否配置成功
		System.out.println(redisson.getConfig().toJSON().toString());
		return redisson;
	}

}

6.3、创建分布式锁的接口DistributedLocker
package com.xu.testboot.redisson;

import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;

public interface DistributedLocker {

	RLock lock(String lockKey);
	 
    RLock lock(String lockKey, long timeout);
 
    RLock lock(String lockKey, TimeUnit unit, long timeout);
 
    boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime);
 
    void unlock(String lockKey);
 
    void unlock(RLock lock);
}
6.4、 创建接口DistributedLocker的实现类
package com.xu.testboot.redisson;

import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RedissonDistributedLocker implements DistributedLocker {

	@Autowired
    private RedissonClient redissonClient;  //RedissonClient已经由配置类生成,这里自动装配即可
 
    //lock(), 拿不到lock就不罢休,不然线程就一直block
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }
 
    //leaseTime为加锁时间,单位为秒
    @Override
    public RLock lock(String lockKey, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, TimeUnit.SECONDS);
        return lock;
    }
    
    //timeout为加锁时间,时间单位由unit确定
    @Override
    public RLock lock(String lockKey, TimeUnit unit ,long timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }
    //tryLock(),马上返回,拿到lock就返回true,不然返回false。
    //带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false.
    @Override
    public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            return false;
        }
    }
    
    @Override
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.unlock();
    }
    
    @Override
    public void unlock(RLock lock) {
        lock.unlock();
    }
}
6.5、使用分布式锁
package com.xu.testboot.controller;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xu.testboot.redisson.DistributedLocker;

@RestController
@RequestMapping("/redisson")
public class AdvMaterialController {

	@Autowired
	private DistributedLocker distributedLocker;

	@RequestMapping("/test")
	public String redissonTest() {
		final String key = "redisson_key";
		for (int i = 0; i < 100; i++) {
			Thread t = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						System.err.println("=============线程开启============" + Thread.currentThread().getName());
						/*
						 * distributedLocker.lock(key,10L); //直接加锁,获取不到锁则一直等待获取锁 Thread.sleep(100);
						 * //获得锁之后可以进行相应的处理
						 * System.err.println("======获得锁后进行相应的操作======"+Thread.currentThread().getName()
						 * ); distributedLocker.unlock(key); //解锁
						 * System.err.println("============================="+Thread.currentThread().
						 * getName());
						 */
						boolean isGetLock = distributedLocker.tryLock(key, TimeUnit.SECONDS, 5L, 10L); // 尝试获取锁,等待5秒,自己获得锁后一直不解锁则10秒后自动解锁
						if (isGetLock) {
							Thread.sleep(100); // 获得锁之后可以进行相应的处理
							System.err.println("======获得锁后进行相应的操作======" + Thread.currentThread().getName());
							// distributedLocker.unlock(key);
							System.err.println("=============================" + Thread.currentThread().getName());
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
			t.start();
		}
		return "OK";
	}
}

博客参考:

https://www.cnblogs.com/thirteen-zxh/p/9187875.html

https://www.cnblogs.com/learnapi/p/9523075.html

https://blog.csdn.net/qq_31256487/article/details/83144088

https://www.cnblogs.com/telwanggs/p/10826887.html

https://blog.csdn.net/qsssyyw/article/details/81562868

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值