如果您对Redis的了解不够深入请关注本栏目,本栏目包括Redis安装,Redis配置文件说明,Redis命令和数据类型说明,Redis持久化配置,Redis主从复制和哨兵机制,Redis Cluster(集群)配置,Redis Predixy 集群,Redis Twemproxy 集群,Redis Codis 集群,Redis 集群对比,RedisBloom 布隆过滤器。
Redis(Remote Dictionary Server)是一种高性能的开源内存数据库,它具有多种用途和功能,可以充当缓存、消息队列、数据库、实时分析和数据处理平台等多种角色。具体功能如下:
下面分别使用 Jedis 、Lettuce 访问Redis 和 在 Spring Boot 使用访问 Redis 的简单示例。
在 pom.xml 添加 jedis
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>3.9.0version>
dependency>
使用连接池对单个Redis实例进行读写
JedisPool pool = new JedisPool("192.168.8.60", 6379);
Jedis resource = pool.getResource();
resource.set("aaa", "111");
System.out.println("read redis 1="+resource.get("aaa"));
使用集群对Redis集群进行读写
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30001));
jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30002));
jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30003));
// jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30004));
// jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30005));
// jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30006));
JedisCluster jedis = new JedisCluster(jedisClusterNodes);
jedis.set("ddd", "1111");
System.out.println("read redis 2="+ jedis.get("aaa"));
以下是完整的测试代码
package top.yiqifu.study.p121;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import java.util.HashSet;
import java.util.Set;
public class Test01_Redis {
public static void main(String[] args) {
// 通过连接池直接读写数据
testResource();
//通过Redis集群(Cluster)读写数据
testCluster();
}
private static void testResource(){
JedisPool pool = new JedisPool("192.168.8.60", 6379);
Jedis resource = pool.getResource();
resource.set("aaa", "111");
System.out.println("read redis 1="+resource.get("aaa"));
}
private static void testCluster(){
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30001));
jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30002));
jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30003));
// jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30004));
// jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30005));
// jedisClusterNodes.add(new HostAndPort("192.168.8.60", 30006));
JedisCluster jedis = new JedisCluster(jedisClusterNodes);
jedis.set("ddd", "1111");
System.out.println("read redis 2="+ jedis.get("aaa"));
}
}
以下给出测试集群搭建的核心命令,具体请参考Redis Cluster(集群)配置。
cd /redis-6.0.6/utils/create-cluster
vi create-cluster
CLUSTER_HOST=192.168.8.60
PROTECTED_MODE=no
./create-cluster start
./create-cluster create
firewall-cmd --permanent --add-port=30001/tcp
firewall-cmd --permanent --add-port=30002/tcp
firewall-cmd --permanent --add-port=30003/tcp
firewall-cmd --permanent --add-port=30004/tcp
firewall-cmd --permanent --add-port=30005/tcp
firewall-cmd --permanent --add-port=30006/tcp
firewall-cmd --reload
开源地址:lettuce-core
在 pom.xml 添加 lettuce-core
<dependency>
<groupId>io.lettucegroupId>
<artifactId>lettuce-coreartifactId>
<version>6.1.10.RELEASEversion>
dependency>
以下使用 lettuce 来读写Redis,lettuce 最大的特点是支持响应式编程(Reactive API)。
package top.yiqifu.study.p121;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.sync.RedisStringCommands;
public class Test02_LettuceRedis {
public static void main(String[] args) {
// 同步/异步方式读写数据
testSync();
}
private static void testSync(){
RedisClient client = RedisClient.create("redis://192.168.8.60:6379");
StatefulRedisConnection<String, String> connection = client.connect();
RedisStringCommands sync = connection.sync();
sync.set("aaa", "111");
System.out.println("read redis 1="+sync.get("aaa"));
RedisAsyncCommands<String, String> async = connection.async();
async.set("bbb", "222");
System.out.println("read redis 2="+async.get("bbb"));
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
<version>2.7.15version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jsonartifactId>
<version>2.7.15version>
dependency>
spring:
redis:
host: 192.168.8.60
port: 6379
@Autowired
RedisTemplate redisTemplate;
private void testObject(){
redisTemplate.opsForValue().set("aaa", "111");
System.out.println("reda redis 1 = "+redisTemplate.opsForValue().get("aaa"));
}
@Autowired
StringRedisTemplate stringRedisTemplate;
private void testString(){
stringRedisTemplate.opsForValue().set("bbb", "222");
System.out.println("read redis 2 = "+stringRedisTemplate.opsForValue().get("bbb"));
}
@Autowired
RedisTemplate redisTemplate;
private void testObject(){
redisTemplate.opsForValue().set("aaa", "111");
System.out.println("reda redis 1 = "+redisTemplate.opsForValue().get("aaa"));
}
@Autowired
RedisTemplate redisTemplate;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
@Qualifier("serializerRedisTemplate")
StringRedisTemplate serializerRedisTemplate;
private void testHash(){
// 方法一:使用 StringRedisTemplate 直接读写hash
HashOperations<String, Object, Object> hash = stringRedisTemplate.opsForHash();
hash.put("someInfo", "name" , "qifu");
hash.put("someInfo", "age" , "30");
System.out.println("read redis 4 = "+hash.entries("someInfo"));//hincrby someInfo age 1
// 创建对象
Person person = new Person();
person.setName("zhang san");
person.setAge(20);
Jackson2HashMapper hashMapper = new Jackson2HashMapper(objectMapper, false);
// 方法二:使用 RedisTemplate 读写 hash 对象
redisTemplate.opsForHash().putAll("person1", hashMapper.toHash(person));
Map personMap1 = redisTemplate.opsForHash().entries("person1");
Person value6 = objectMapper.convertValue(personMap1, Person.class);
System.out.println("read redis 6 = "+value6.getName());
// 方法三:使用 StringRedisTemplate 读写 hash 对象
// stringRedisTemplate 需设置 ValueSerializer ,因为age是Integer类型
stringRedisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
stringRedisTemplate.opsForHash().putAll("person2", hashMapper.toHash(person));
Map personMap2 = stringRedisTemplate.opsForHash().entries("person2");
Person value7 = objectMapper.convertValue(personMap2, Person.class);
System.out.println("read redis 7 = "+value7.getName());
// 方法四:使用自定义 serializerRedisTemplate 读写 hash 对象
serializerRedisTemplate.opsForHash().putAll("person3", hashMapper.toHash(person));
Map personMap3 = serializerRedisTemplate.opsForHash().entries("person3");
Person value8 = objectMapper.convertValue(personMap3, Person.class);
System.out.println("read redis 8 = "+value8.getName());
}
@Autowired
StringRedisTemplate stringRedisTemplate;
private void testPubsub(){
//pub/sub
stringRedisTemplate.getConnectionFactory().getConnection().subscribe(new MessageListener() {
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println("sub redis = "+new String(message.getBody()));
}
}, "xxx".getBytes());
stringRedisTemplate.convertAndSend("xxx","yyy");
}
TestRedis.java
package top.yiqifu.study.p211_redis;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.hash.Jackson2HashMapper;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class TestRedis {
@Autowired
RedisTemplate redisTemplate;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
@Qualifier("serializerRedisTemplate")
StringRedisTemplate serializerRedisTemplate;
@Autowired
ObjectMapper objectMapper;
public void test(){
// 基于 RedisTemplate 测试Redis全类型的读写,如 object
this.testObject();
// 基于 StringRedisTemplate 测试Redis字符串类型的读写,如 string
this.testString();
// 基于 RedisConnection 测试Redis更底层的字节类型的读写,如 byte[]
this.testBytes();
// 基于 StringRedisTemplate 测试Redis的Hash类型的读写,如 hash
this.testHash();
// 基于 StringRedisTemplate 测试Redis的发布、订阅
this.testPubsub();
}
private void testObject(){
redisTemplate.opsForValue().set("aaa", "111");
System.out.println("reda redis 1 = "+redisTemplate.opsForValue().get("aaa"));
}
private void testString(){
stringRedisTemplate.opsForValue().set("bbb", "222");
System.out.println("read redis 2 = "+stringRedisTemplate.opsForValue().get("bbb"));
}
private void testBytes(){
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.set("ccc".getBytes(), "333".getBytes());
System.out.println("read redis 3 = "+new String(connection.get("ccc".getBytes())));
}
private void testHash(){
// 方法一:使用 StringRedisTemplate 直接读写hash
HashOperations<String, Object, Object> hash = stringRedisTemplate.opsForHash();
hash.put("someInfo", "name" , "qifu");
hash.put("someInfo", "age" , "30");
System.out.println("read redis 4 = "+hash.entries("someInfo"));//hincrby someInfo age 1
// 创建对象
Person person = new Person();
person.setName("zhang san");
person.setAge(20);
Jackson2HashMapper hashMapper = new Jackson2HashMapper(objectMapper, false);
// 方法二:使用 RedisTemplate 读写 hash 对象
redisTemplate.opsForHash().putAll("person1", hashMapper.toHash(person));
Map personMap1 = redisTemplate.opsForHash().entries("person1");
Person value6 = objectMapper.convertValue(personMap1, Person.class);
System.out.println("read redis 6 = "+value6.getName());
// 方法三:使用 StringRedisTemplate 读写 hash 对象
// stringRedisTemplate 需设置 ValueSerializer ,因为age是Integer类型
stringRedisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
stringRedisTemplate.opsForHash().putAll("person2", hashMapper.toHash(person));
Map personMap2 = stringRedisTemplate.opsForHash().entries("person2");
Person value7 = objectMapper.convertValue(personMap2, Person.class);
System.out.println("read redis 7 = "+value7.getName());
// 方法四:使用自定义 serializerRedisTemplate 读写 hash 对象
serializerRedisTemplate.opsForHash().putAll("person3", hashMapper.toHash(person));
Map personMap3 = serializerRedisTemplate.opsForHash().entries("person3");
Person value8 = objectMapper.convertValue(personMap3, Person.class);
System.out.println("read redis 8 = "+value8.getName());
}
private void testPubsub(){
//pub/sub
stringRedisTemplate.getConnectionFactory().getConnection().subscribe(new MessageListener() {
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println("sub redis = "+new String(message.getBody()));
}
}, "xxx".getBytes());
stringRedisTemplate.convertAndSend("xxx","yyy");
}
}
Config.java
package top.yiqifu.study.p211_redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import javax.annotation.Resource;
@Configuration
public class Config {
@Resource
RedisConnectionFactory factory;
@Bean("serializerRedisTemplate")
public StringRedisTemplate getRedisTemplate(){
StringRedisTemplate template = new StringRedisTemplate(factory);
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return template;
}
}
RedisSpringBootApplication.java
package top.yiqifu.study.p211_redis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class RedisSpringBootApplication {
public static void main(String[] args){
ConfigurableApplicationContext context = SpringApplication.run(RedisSpringBootApplication.class, args);
TestRedis bean = context.getBean(TestRedis.class);
bean.test();
}
}
在新版本(版本大于2.7)的SpringBoot中,以下写法会报错“Could not autowire. No beans of ‘RedisConnectionFactory’ type found”,如下写法:
@Configuration
public class Config {
@Bean("serializerRedisTemplate")
public StringRedisTemplate getRedisTemplate(RedisConnectionFactory factory){
StringRedisTemplate template = new StringRedisTemplate(factory);
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return template;
}
}
要使用@Resource注解的属性注入,修改后的代码为
@Configuration
public class Config {
@Resource
RedisConnectionFactory factory;
@Bean("serializerRedisTemplate")
public StringRedisTemplate getRedisTemplate(){
StringRedisTemplate template = new StringRedisTemplate(factory);
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return template;
}
}