我们在使用redis的时候,需要使用驱动来链接redis,通过驱动去操作redis,我们可以直接使用redis提供的基本的驱动来操作数据库但是为了效率我们一般会使用开源的解决方案来进行操作,目前主流的开源解决方案有jedis,redission,lettuce三种解决方案,其中jedis是同步的方案,现在包括spring-data也已经不再内置使用了,替换成了lettuce,那有些人就说了,那我们学习lettuce不就行了么?你说的没问题,为什么有三种呢,我们其实使用一种就可以了啊,是的没有问题,但是用哪个我们需要来分析分析。jedis出现的时间比较长了,接触redis比较早的人可能使用的都是jedis,但是随着现代系统的多核和异步,为了不断提高的吞吐量,异步非阻塞线程模型大行其道,这里面非常热门的框架就是Netty,Netty因其设计优秀,应用面广,实际使用的场景广泛,很多大型框架比如hadoop,dubbo等许多的底层都是通过Netty来实现的通信。所以我们就专门针对异步的且基于netty的Redis驱动来分析,redission和lettuce都是基于netty的也就是说他俩都是异步非阻塞的,但是他们有什么区别呢?其实在使用语法上面有一些区别,redission对结果做了一层包装,通过包装类来进行一些额外的操作来达到异步操作,并且redission提供了额外的分部署锁功能,可能很多人并不会去研究这个功能或者说公司内有大牛自己来实现分布式锁,这些就另当别论了。我们今天就来说说redission的使用方式吧,lettuce的使用说明在我之前的博客中有说明,如果需要可以自行查找。
现在我们就来说说具体的redission的配置,通过配置之后就可以使用了,没用什么特别复杂的地方,先上demo,在根据demo来说说细节。
import java.io.IOException;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedisConfig {
@Bean(destroyMethod = "shutdown")
RedissonClient redisson() throws IOException {
Config config = new Config();
//config.useClusterServers().addNodeAddress("127.0.0.1:6379");
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
redission的配置比较简单,配置一个RedissonClient就可以了,默认的配置支持redis的所有实现方式,如集群,单节点,哨兵,副本等都可以进行配置,这里需要注意的是配置的线程模型,默认配置的线程是64个,我们根据需要来进行配置及连接超时时间,请求超时时间,是否长连接等参数进行配置,这里没有什么特别的参数,基本就是服务器连接的一些参数配置,根据实际业务进行性能优化的点大部分都在这里进行控制,代码的性能优化主要还是根据规范对key的可读性,长度等进行控制,对值得长度进行控制,对结合的元素个数进行控制,以及序列化的性能,主要就是这几方面的处理。
import java.util.concurrent.TimeUnit;
import org.redisson.api.RBucket;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class RedisDao {
@Autowired
private RedissonClient redissonClient;
// -----------------------------------------------------------------------
public String getString(String key) {
RBucket<Object> result = this.redissonClient.getBucket(key);
return result.get().toString();
}
public void setString(String key, Object value) {
RBucket<Object> result = this.redissonClient.getBucket(key);
if (!result.isExists()) {
result.set(value, 5, TimeUnit.MINUTES);
}
}
public boolean hasString(String key) {
RBucket<Object> result = this.redissonClient.getBucket(key);
if (result.isExists()) {
return true;
} else {
return false;
}
}
public long incr(String key, long delta) {
return this.redissonClient.getAtomicLong(key).addAndGet(delta);
}
// -----------------------------------------------------------------------
public void lock() {
RCountDownLatch countDown = redissonClient.getCountDownLatch("aa");
countDown.trySetCount(1);
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
RCountDownLatch latch = redissonClient.getCountDownLatch("countDownLatchName");
latch.countDown();
RReadWriteLock rwlock = redissonClient.getReadWriteLock("lockName");
rwlock.readLock().lock();
rwlock.writeLock().lock();
rwlock.readLock().lock(10, TimeUnit.SECONDS);
rwlock.writeLock().lock(10, TimeUnit.SECONDS);
try {
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
boolean res1 = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
redission中包含了我们了解的常用锁的类型,基本的可重入锁,读写锁,以及CountDownLatch的设置及使用,但是他们是分布式锁,以往我们JUC提供的锁都是在单线程的线程模型中使用的,当多个进程多个线程来操作一个无锁的共享资源的时候,就会出现线程不安全的问题,就是我们多次执行后结果和单个线程执行时结果的不一致,为了让线程一致我们是需要一些处理办法的,那就是分布式锁,通过锁进行多线程的同步来进行资源隔离来实现对资源的访问控制,从而达到线程安全,所以根据实际中的业务需要,我们可以根据自身的技术实力及业务需要来实现自己的分布式锁,实现的方式主要有redis和zookeeper,有需要的可以自行百度学习,稍后博主自己也会对该方面知识进行学习整理。通过上面的整理相信大家已经对redission已经有了一个初步的认识,具体的编程语法需要自己去根据数据类型具体学习。