Spring整合Redis使用

本文详细介绍如何在Spring框架中整合Redis,包括使用Jedis客户端库、配置连接池、实现集群式连接池,以及提供一个用于简化Redis操作的工具类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring整合Redis使用

1. 描述
Redis的话,基于内存的查找确实快,也支持各种各样的数据结构,set、List、String、散列和Map,不过底层结构应该是类似json实现,这倒是无所谓,关键用它做缓存效果确实Ok,什么SSO都会用到它,实际开发中挺常用的。
不过常用的命令自行百度,感觉挺简单的,主要是操作Redis也需要第三方提供的支持,C++,Java,.Net,Pytho…各种语言都需要各个第三方供应商提供的client,本文使用java,市场上大量使用的是jedis。

2. 依赖

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

3. Redis服务简介
在这里插入图片描述
在Windows系统讲解吧,按照网上的教程我相信大部分人包括我自己也是这样,当年启动Redis就直接执行redis-server.exe,当时也不看就在它下面的文档RedisService.docx,就算打开文档一看是英文果断关闭,这就是小白的通病啊。
正确方式,应该以服务方式部署和卸载,文档里的instance描述如下:

Installing the Service
--service-install
This must be the first argument on the redis-server command line. Arguments after this are passed in the order they occur to Redis when the service is launched. The service will be configured as Autostart and will be launched as "NT AUTHORITY\NetworkService". Upon successful installation a success message will be displayed and Redis will exit.
This command does not start the service.
For instance:
redis-server --service-install redis.windows.conf --loglevel verbose

这个就是在Redis配置文件的那层执行:redis-server --service-install redis.windows.conf --loglevel verbose命令,效果如图:
在这里插入图片描述
是不是感觉高大上许多,比你执行那个黑窗口干净多了,卸载命令文档也有:

redis-server --service-uninstall

内存大小在配置redis.windows.conf中配置,大小为200MB:

# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
 maxmemory 200mb

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:

服务起来了,连接到Redis呢?redis-cli.exe该执行文件会帮助你,当然不建议直接点击它运行,因为这样永远只能连接一台Redis,如果是集群呢?所以使用下面命令:

redis-cli.exe -h 127.0.0.1 -p 6379

测试连接成功与否
在这里插入图片描述
ping一下,如果收到PONG,那就恭喜你!
具体命令我就不讲了,什么set,get,flushAll,keys *,select db…自行百度
4. 简单的Java操作Redis代码

     public static void main(String[] args) {
        // 构造jedis对象
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 向redis中添加数据
        jedis.set("mytest", "123");
        // 从redis中读取数据
        String value = jedis.get("mytest");

        System.out.println(value);
        // 关闭连接
        jedis.close();

    }

这个一看就明白了,连接到Redis,然后存入数据,取出数据,这个Demo让我们知道Jedis的使用。当然这远远不够啦。

 public static void main(String[] args) {
        // 构建连接池配置信息
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 设置最大连接数
        jedisPoolConfig.setMaxTotal(50);

        // 构建连接池
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);

        // 从连接池中获取连接
        Jedis jedis = jedisPool.getResource();

        // 读取数据
        System.out.println(jedis.get("mytest"));

        // 将连接还回到连接池中
        jedisPool.returnResource(jedis);

        // 释放连接池
        jedisPool.close();

    }

这个让我们知道连接池的存在,ok吧。

5. 集群式连接池
单个Redis的存在并不适用于现在互联网的发展,毕竟集群式的模型才是趋势,不过谈到Redis集群呢,我确实没去深入了解,简单的知道两种集群,一种是Redis官方提供的集群,做的比另一个叫做分片式集群好,为什么呢,分片式集群是一种固定数量的集群,一旦总的数量确定后,每台Redis服务都有对应通过总数量算出的唯一HashCode值,集群的负载均衡就是通过这个值去分配的,缺点是加入另一台Redis时,平衡打破,规则不成立。
但是我们依然使用分片式集群,why?简单啊!!
举个栗子:

 public static void main(String[] args) {
        // 构建连接池配置信息
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        // 设置最大连接数
        poolConfig.setMaxTotal(50);

        // 定义集群信息
        List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
        shards.add(new JedisShardInfo("127.0.0.1", 6379));

        // 定义集群连接池
        ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, shards);
        ShardedJedis shardedJedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            shardedJedis = shardedJedisPool.getResource();

            // 从redis中获取数据
            String value = shardedJedis.get("mytest");
            System.out.println(value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != shardedJedis) {
                // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
                shardedJedis.close();
            }
        }

        // 关闭连接池
        shardedJedisPool.close();

    }

很简单吧,就是将一个Redis服务加入List中,然后再传入ShardedJedisPool 中,当然有借有还还是Pool这个持有的属性,连接记得释放,但是注意下: shardedJedisPool.close(); 关闭连接池就不要随便操作啦,毕竟一个服务一般都不会停止的,这个集群的生命周期和服务一样长就行了。
对应Spring配置:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
	
	<!--redis连接池  -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.MaxTotal}"/>
	</bean>
	<!-- 分片式集群连接池 -->
	<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
		<constructor-arg index="0" ref="jedisPoolConfig"/>
		<constructor-arg index="1">
			<list>
				<bean class="redis.clients.jedis.JedisShardInfo">
					<constructor-arg index="0" value="${redis.node1.ip}"/>
					<constructor-arg index="1" value="${redis.node1.port}"/>
				</bean>
			</list>
		</constructor-arg>
	</bean>

</beans>

这个配置也是很好理解了,你要是仔细看了上面的Demo很容易明白就是将【连接池最大连接数】和所需配置的【Redis节点】作为构造参数传入ShardedJedisPool中。
这里提供properties配置参数:

#最大连接数量
redis.MaxTotal=100
#节点1
redis.node1.ip=127.0.0.1
redis.node1.port=6379
#节点2
redis.node1.ip=127.0.0.1
redis.node1.port=4455

6. RedisService工具类【基本功能】
先来看一个接口:

	package com.taotao.common.service;

	public interface Function<T, E> {
 	   T callback(E e);
	}

入参:E,返回:T 都是泛型,为什么这样写,为了简化RedisService中的重复代码,这个思想其实是模仿js回调的设计,多看看,其实挺有意思的。

package com.taotao.common.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

@Service
public class RedisService {

    @Autowired(required = false)
    private ShardedJedisPool shardedJedisPool;

    private <T> T execute(Function<T, ShardedJedis> function) {
        // 定义集群连接池
        ShardedJedis shardedJedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            shardedJedis = shardedJedisPool.getResource();
            return function.callback(shardedJedis);
        } finally {
            if (null != shardedJedis) {
                // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
                shardedJedis.close();
            }
        }
    }

    public String set(final String key, final String value) {
        return this.execute(new Function<String, ShardedJedis>() {
            @Override
            public String callback(ShardedJedis shardedJedis) {
                return shardedJedis.set(key, value);
            }

        });
    }

    public String get(final String key) {
        return this.execute(new Function<String, ShardedJedis>() {
            @Override
            public String callback(ShardedJedis shardedJedis) {
                return shardedJedis.get(key);
            }
        });
    }
    
    public Long del(final String key) {
        return this.execute(new Function<Long, ShardedJedis>() {
            @Override
            public Long callback(ShardedJedis shardedJedis) {
                return shardedJedis.del(key);
            }
        });
    }
    
    public Long expire(final String key, final Integer seconds) {
        return this.execute(new Function<Long, ShardedJedis>() {
            @Override
            public Long callback(ShardedJedis shardedJedis) {
                return shardedJedis.expire(key, seconds);
            }

        });
    }
    
    public String set(final String key, final String value, final Integer seconds) {
        return this.execute(new Function<String, ShardedJedis>() {
            @Override
            public String callback(ShardedJedis shardedJedis) {
                String res = shardedJedis.set(key, value);
                shardedJedis.expire(key, seconds);
                return res;
            }

        });
    }
}

最后还是说明下,下面函数里的代码其实是重复的,操作都是拿连接和关闭连接,我们定义这个execute函数就是为了让其他方法公用该函数,注意函数入参是Function接口,我们将返回的结果交由调用者去实现,由调用者确定Function返回类型T,入参是ShardedJedis不用考虑吧,因为所有操作都需要用到它,这种设计思想可以多学习:

 private <T> T execute(Function<T, ShardedJedis> function) {
        // 定义集群连接池
        ShardedJedis shardedJedis = null;
        try {
            // 从连接池中获取到jedis分片对象
            shardedJedis = shardedJedisPool.getResource();
            return function.callback(shardedJedis);
        } finally {
            if (null != shardedJedis) {
                // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
                shardedJedis.close();
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值