(六)Redis的java客户端
开放远程连接
CentOS7
# 开放端口
firewall-cmd --permanent --add-port=8080/tcp
# 查询端口是否开放
firewall-cmd --query-port=8080/tcp
# 重新载入
firewall-cmd --reload
# 移除指定的端口
firewall-cmd --permanent --remove-port=8080/tcp
1、redis非本机要开放远程连接端口和配置
Redis开放远程连接
1、开放6379端口
2、修改配置
- 修改 protected-mode yes 改为:protected-mode no
- 注释掉 #bind 127.0.0.1,或绑定客户端ip
Jedis连接
依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.1</version>
</dependency>
单节点:
@Test
public void testJedis() {
try (Jedis connect = new Jedis("192.168.0.109", 7001)) {
String set = connect.set("name", "ha");
Assert.assertEquals(connect.get("name"), "ha");
}
}
连接池
@Test
public void testJedisPool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(8);
config.setMaxIdle(8);
config.setMinIdle(0);
config.setMaxWaitMillis(8);
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
// 连接耗尽的时候,是否阻塞,false会抛出异常,true阻塞直到超时。默认为true。
config.setBlockWhenExhausted(true);
// JedisPool pool = new JedisPool(config, "192.168.0.109", 6379, 2000, password);
JedisPool pool = new JedisPool(config, "192.168.0.109", 6379, 2000);
try (Jedis client = pool.getResource()) {
client.set("name", "aaa");
Assert.assertEquals(client.get("name"), "ld");
}
}
sentinel
@Test
public void testRedisSentinel() throws InterruptedException {
String masterName = "mymaster";
Set<String> sentinelSet = new HashSet<>();
sentinelSet.add("192.168.0.109:26379");
sentinelSet.add("192.168.0.109:26380");
sentinelSet.add("192.168.0.109:26381");
JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinelSet);
int count = 0;
while (true) {
try (Jedis resource = pool.getResource()) {
HostAndPort currentHostMaster = pool.getCurrentHostMaster();
String host = currentHostMaster.getHost();
int port = currentHostMaster.getPort();
resource.set("host" + count, host);
resource.set("port" + count, String.valueOf(port));
List<String> valueList = resource.mget("host" + count, "port" + count);
log.info("host" + count + " {}, port" + count + " {};", valueList.get(0), valueList.get(1));
} catch (Exception e) {
e.printStackTrace();
}
Thread.sleep(1000);
count++;
if (count == 10000) {
break;
}
log.info("count = {}", count);
}
}
集群
@Slf4j
public class JedisClusterTest {
private JedisCluster jedisCluster;
@Before
public void init() {
Set<HostAndPort> nodeList = new HashSet<>();
nodeList.add(new HostAndPort("192.168.0.109",6379));
nodeList.add(new HostAndPort("192.168.0.110",6379));
nodeList.add(new HostAndPort("192.168.0.111",6379));
nodeList.add(new HostAndPort("192.168.0.109",6380));
nodeList.add(new HostAndPort("192.168.0.110",6380));
nodeList.add(new HostAndPort("192.168.0.111",6380));
this.jedisCluster = new JedisCluster(nodeList, 2000);
}
@Test
public void testJedisCluster() {
for (int i = 0; i < 1000; i++) {
String result = jedisCluster.set("key" + i, "value" + i);
log.info("result: {}", result);
}
for (int i = 0; i < 1000; i++) {
String value = jedisCluster.get("key" + i);
log.info("key: {}, value: {}", "key" + i, value);
}
// 不能使用keys *
// Set<String> keys = jedisCluster.keys("*");
// keys.forEach(log::info);
}
}
springboot-redis
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
单节点使用
- 配置
spring:
redis:
host: 127.0.0.1
port: 6379
- 配置类
/**
* 基本配置,如果没有额外配置,可不编写此类配置文件,直接使用默认自动配置
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
- 使用
@SpringBootTest(classes = RedisApplication.class)
@RunWith(SpringRunner.class)
public class RedisTemplateTest {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
public void test() throws Exception {
// 保存字符串
stringRedisTemplate.opsForValue().set("aaa", "222");
Assert.assertEquals("222", stringRedisTemplate.opsForValue().get("aaa"));
}
}
缓存使用
- service接口
package com.zuizui.boot.redis.service;
import com.zuizui.boot.redis.entity.SysUser;
/**
* @author zuier
*/
public interface SysUserService {
/**
* 根据id获取用户
*
* @param id Long
* @return SysUser
*/
SysUser getById(Long id);
/**
* 存储user
*
* @param sysUser SysUser
* @return SysUser
*/
SysUser save(SysUser sysUser);
/**
* 更新user
*
* @param sysUser SysUser
* @return SysUser
*/
SysUser update(SysUser sysUser);
/**
* 根据id删除
*
* @param id Long
*/
void del(Long id);
}
- service实现
package com.zuizui.boot.redis.service.impl;
import com.zuizui.boot.redis.entity.SysUser;
import com.zuizui.boot.redis.service.SysUserService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author zuier
*/
@Service
@CacheConfig(cacheNames = "sys-user")
public class SysUserServiceImpl implements SysUserService {
private Map<Long, SysUser> sysUserMap = new ConcurrentHashMap<>();
{
Date date = new Date();
for (int i = 0; i < 10; i++) {
sysUserMap.put((long) i, new SysUser((long) i, "user" + i, "pass" + i, "name" + i, "email" + i, "phone" + i, date, date, 0));
}
}
@Override
@Cacheable
public SysUser getById(Long id) {
return sysUserMap.get(id);
}
@Override
@CachePut(cacheNames = "sys-user", key = "#sysUser.id")
public SysUser save(SysUser sysUser) {
sysUserMap.put(sysUser.getId(), sysUser);
return sysUser;
}
@Override
@CachePut(key = "#sysUser.id")
public SysUser update(SysUser sysUser) {
SysUser sysUser1 = sysUserMap.get(sysUser.getId());
if (sysUser1 == null) {
return null;
}
sysUserMap.put(sysUser.getId(), sysUser);
return sysUser;
}
@Override
@CacheEvict
public void del(Long id) {
sysUserMap.remove(id);
}
}
- 缓存配置:可在注解中指定
package com.zuizui.boot.redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* @author zuier
*/
@Configuration
public class RedisCacheConfig {
/**
* 缓存key生成器
* @return KeyGenerator
*/
@Bean
public KeyGenerator simpleKeyGenerator() {
return (o, method, objects) -> {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(o.getClass().getSimpleName());
stringBuilder.append(".");
stringBuilder.append(method.getName());
stringBuilder.append("[");
for (Object obj : objects) {
stringBuilder.append(obj.toString());
}
stringBuilder.append("]");
return stringBuilder.toString();
};
}
/**
* 缓存管理器
* @param redisConnectionFactory RedisConnectionFactory
* @return CacheManager
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
// 默认策略,未配置的 key 会使用这个
this.getRedisCacheConfigurationWithTtl(600),
// 指定 key 策略
this.getRedisCacheConfigurationMap()
);
}
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(2);
redisCacheConfigurationMap.put("cacheName1", this.getRedisCacheConfigurationWithTtl(3000));
redisCacheConfigurationMap.put("cacheName2", this.getRedisCacheConfigurationWithTtl(18000));
return redisCacheConfigurationMap;
}
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds));
return redisCacheConfiguration;
}
}
cluster 集群
- 配置:application.yml
spring:
redis:
cluster:
max-redirects: 5
nodes:
- 192.168.0.109:6379
- 192.168.0.109:6380
- 192.168.0.110:6379
- 192.168.0.110:6380
- 192.168.0.111:6379
- 192.168.0.111:6380
timeout: 1000ms
jedis:
pool:
max-wait: 1ms
max-idle: 8
min-idle: 0
max-active: 50
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RedisClusterApplication.class)
public class RedisClusterTest {
@Resource
private RedisTemplate redisTemplate;
@Test
public void env() {
Assert.assertNotNull(redisTemplate);
}
@Test
@SuppressWarnings("unchecked")
public void string() {
for (int i = 0; i < 10; i++) {
redisTemplate.opsForValue().set("spring" + i, "boot" + i);
Object spring = redisTemplate.opsForValue().get("spring" + i);
Assert.assertEquals("boot" + i, String.valueOf(spring));
}
}
}