我們在使用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已經有了一個初步的認識,具體的編程語法需要自己去根據數據類型具體學習。