Lettuce和Jedis

Lettuce

Sentinel

com.lambdaworks.redis.RedisClient#connectSentinel(com.lambdaworks.redis.codec.RedisCodec<K,V>, com.lambdaworks.redis.RedisURI, com.lambdaworks.redis.RedisClient.Timeout)

Jedis

配置 Jedis

1.添加 Jedis 的 Maven 依赖
2.设置服务端
设置服务器防火墙关闭或放行 6379 端口(redis 占用)
然后关闭服务器的保护模式,因为保护模式下不能写入数据

1
2
CONFIG SET protected-mode no
config rewrite

(或直接修改 redis.conf 中 protected-mode
或在运行服务器的配置中加上–protected-mode no
或 Setup a bind address or an authentication password)
然后注释掉 redis.conf 中的 bind 127.0.0.1,或者在后面添上本机的 ip

  1. 普通单例连接
    1
    2
    3
    4
    5
    Jedis jedis = new Jedis(host, 6379);
    jedis.set("name", "bar");
    String name = jedis.get("name");
    System.out.println(name);
    jedis.close();
  2. 使用连接池连接
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 配置连接池
    JedisPoolConfig config = new JedisPoolConfig();
    config.setMaxTotal(30); // 最大连接数
    config.setMaxIdle(2); // 最大连接空闲数
    JedisPool pool =
    new JedisPool(config, host, 6379);
    // 从连接池中获取连接
    Jedis jedis = pool.getResource();
    jedis.set("name", "李四");
    String name = jedis.get("name");
    System.out.println(name);
    // 关闭,返回到连接池
    jedis.close();

并发安全问题

Jedis 不是并发安全的,如果有并发安全的需求,可以考虑采用 apache 的 commons-pool 对象池进行包装,或者,换用一个更先进的 Redis 客户端 Lettuce

spring-data-redis

1.引入依赖 spring-data-redis
2.创建 redis 缓冲配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 配置头部用于被Spring识别
@Configuration
@EnableCaching
public class RedisCacheConfig {
private volatile JedisConnectionFactory mJedisConnectionFactory;
private volatile RedisTemplate<String, String> mRedisTemplate;
private volatile RedisCacheManager mRedisCacheManager;
public RedisCacheConfig() {
super();
}
public RedisCacheConfig(JedisConnectionFactory mJedisConnectionFactory, RedisTemplate<String,String> mRedisTemplate,
RedisCacheManager mRedisCacheManager) {
super();
this.mJedisConnectionFactory = mJedisConnectionFactory;
this.mRedisTemplate = mRedisTemplate;
this.mRedisCacheManager = mRedisCacheManager;
}
public JedisConnectionFactory redisConnectionFactory() {
return mJedisConnectionFactory;
}
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
return mRedisTemplate;
}
public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
return mRedisCacheManager;
}
// 用于生成主键
@Bean
public KeyGenerator customKeyGenerator() {
return new KeyGenerator() {
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
}

3.创建 redis 属性文件 redis.properties

1
2
3
4
5
6
7
8
9
10
redis.host=192.168.157.128
redis.port=6379
redis.pass=1234
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
#借出连接时不要测试,否则很影响性能
redis.testOnBorrow=true
redis.dbIndex=0
redis.expiration=30

当然必须在 Spring 配置文件中引入属性文件扫描标签
4.在 Spring 配置文件中引入 redis
问题
ERR Client sent AUTH, but no password is set
因为 redis 没有配置密码而建立连接时却发送了密码,所以出错,解决办法是在下面 jedisConnectionFactory 标签中去掉 password 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- 配置JedisPoolConfig实例 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- 配置JedisConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="password" value="${redis.pass}"/>
<property name="database" value="${redis.dbIndex}"/>
<property name="poolConfig" ref="poolConfig"/>
</bean>
<!-- 配置RedisTemplate -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
</bean>
<!-- 配置RedisCacheManager -->
<bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg name="redisOperations" ref="redisTemplate" />
<property name="defaultExpiration" value="${redis.expiration}"/>
</bean>
<!-- 配置RedisCacheConfig -->
<bean id="redisCacheConfig" class="com.ebuy.util.RedisCacheConfig">
<constructor-arg ref="jedisConnectionFactory" />
<constructor-arg ref="redisTemplate" />
<constructor-arg ref="redisCacheManager" />
</bean>

5.测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 缓存
@Cacheable 缓存返回值,下次调用时会优先使用缓存数据
value 缓存将被存到的地方
@CacgeEvict 清除缓存
*/
@CacheEvict(value = {"save"}, allEntries = true)
public void save(TbContent content) {
contentDao.insert(content);
}
@Cacheable("findall")
public TbContent findall() {
TbContent content = new TbContent();
content.setCategoryId((long) 1);
return content;
}

测试时可以在 findall 中设置打印语句,连续调用 findall 两次,若第二次没有输出东西则说明使用了缓存。
6.配置连接池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="30" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="10" />
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!-- redis单机 通过连接池 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="close">
<constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
<constructor-arg name="host" value="172.16.205.141"/>
<constructor-arg name="port" value="6379"/>
</bean>

7.测试

1
2
3
4
5
6
7
JedisPool pool =
(JedisPool) applicationContext.getBean("jedisPool");
Jedis jedis = pool.getResource();
jedis.set("name", "李四");
String name = jedis.get("name");
System.out.println(name);
jedis.close();