Redisson简介

Redisson是Redis服务器上的分布式可伸缩Java数据结构----驻内存数据网格(In-Memory Data Grid,IMDG)。底层使用netty框架,并提供了与java对象相对应的分布式对象、分布式集合、分布式锁和同步器、分布式服务等一系列的Redisson的分布式对象。

IMDG是什么

将内存作为存储介质,在对主存的使用上IMDG有以下特性:
数据是分布式存储在多台服务器上,可以根据需要增减服务器
IMDG需要克服的核心问题是容量限制和可靠性。通过水平扩展克服了内存容量的限制,通过复制保证可靠性
一般使用堆外内存降低垃圾回收压力

与Spring Boot集成

1、Maven依赖

<dependency>
         <groupId>org.redisson</groupId>
         <artifactId>redisson-spring-boot-starter</artifactId>
         <version>3.11.6</version>
    </dependency>

2、添加配置文件redisson-xx.yml

# common spring boot settings

spring.redis.database=
spring.redis.host=
spring.redis.port=
spring.redis.password=
# Redisson settings
#path to config - redisson.yaml
spring.redis.redisson.config=classpath:redisson-xx.yaml

3、配置类创建RedissonClient

@Configuration
public class RedssonConfig {
    @Bean(destroyMethod="shutdown")
    public RedissonClient redisson() throws IOException {
        RedissonClient redisson = Redisson.create(
                Config.fromYAML(new ClassPathResource("redisson-xx.yml").getInputStream()));
        return redisson;
    }
}

之后通过@Autowired注入RedissonClient 就可以使用Redisson分布式应用了(例如秒杀系统)。

单个集合分片

自动分片功能是将单个数据结构拆分,根据分片算法分为若干片段(默认231,231个片段分到4个主节点,每个大约57个),均匀分布在整个集群。可以充分利用集群内存资源,可以提高读性能,读性能随集群扩张而提升。

分布式对象

每一个Redisson对象都有一个Redis数据实例相对应。
1、通用对象桶
Redisson分布式对象RBucket,可以存放任意类型对象
2、二进制流
Redisson分布式对象RBinaryStream,InputStream和OutoutStream接口实现
3、地理空间对象桶
Reddisson分布式RGo,储存于地理位置有关的对象桶
4、BitSet
Reddisson分布式RBitSet,是分布式的可伸缩位向量
通过实现RClusteredBitSet接口,可以在集群环境下数据分片
5、布隆过滤器
Reddisson利用Redis实现了java分布式的布隆过滤器RBloomFilter

public class BloomFilterExamples {

    public static void main(String[] args) {
        // connects to 127.0.0.1:6379 by default
        RedissonClient redisson = Redisson.create();

        RBloomFilter<String> bloomFilter = redisson.getBloomFilter("bloomFilter");
        bloomFilter.tryInit(100_000_000, 0.03);
        
        bloomFilter.add("a");
        bloomFilter.add("b");
        bloomFilter.add("c");
        bloomFilter.add("d");
        
        bloomFilter.getExpectedInsertions();
        bloomFilter.getFalseProbability();
        bloomFilter.getHashIterations();
        
        bloomFilter.contains("a");
        
        bloomFilter.count();
        
        redisson.shutdown();
    }
    
}

实现RClusteredBloomFilter接口,可以分片。通过压缩未使用的比特位来释放集群内存空间
6、基数估计算法(RHyperLogLog)
可以在有限的空间通过概率算法统计大量数据
7、限流器(RRateLimiter )
可以用来在分布式环境下限制请求方的调用频率。适用于不同或相同的Reddisson实例的多线程限流。并不保证公平性

public class RateLimiterExamples {

    public static void main(String[] args) throws InterruptedException {
        // connects to 127.0.0.1:6379 by default
        RedissonClient redisson = Redisson.create();

        RRateLimiter limiter = redisson.getRateLimiter("myLimiter");
        // one permit per 2 seconds
        limiter.trySetRate(RateType.OVERALL, 1, 2, RateIntervalUnit.SECONDS);
        
        CountDownLatch latch = new CountDownLatch(2);
        limiter.acquire(1);
        latch.countDown();

        Thread t = new Thread(() -> {
            limiter.acquire(1);
            
            latch.countDown();
        });
        t.start();
        t.join();
        
        latch.await();
        
        redisson.shutdown();
    }
    
}

及原子整长形(RAtomicLong )、原子双精度浮点(RAtomicDouble )、话题(订阅分发)(RTopic )、整长型累加器(RLongAdder )、双精度浮点累加器(RLongDouble )等分布式对象

分布式集合

在Redis分布式的集合元素与java对象相对应。包括:映射、多值映射(Multimap)、集(Set)、有序集(SortedSet)、计分排序集(ScoredSortedSet)、字典排序集(LexSortedSet)、列表(List)、队列(Queue)、双端队列(Deque)、阻塞队列(Blocking Queue)

映射(RMap)

映射类型按照特性主要分为三类:元素淘汰、本地缓存、数据分片。
1、元素淘汰(Eviction)类:对映射中每个元素单独设置有效时间和最长闲置时间。保留了元素的插入顺序。不支持散列(hash)的元素淘汰,过期元素通过EvictionScheduler实例定期清理。实现类RMapCache
2、本地缓存(LocalCache)类:本地缓存也叫就近缓存,主要用在特定场景下。映射缓存上的高度频繁的读取操作,使网络通信被视为瓶颈的情况下。较分布式映射提高45倍。实现类RLocalCachedMap
3、数据分片(Sharding):利用分库的原理,将单一映射结构切分若干,并均匀分布在集群的各个槽里。可以突破Redis自身的容量限制,可以随集群的扩大而增长,也可以使读写性能和元素淘汰能力随之线性增长。主要实现类RClusteredMap
当然还有其他类型,比如映射监听器、LRU有界映射
映射监听器:监听元素的添加(EntryCreatedListener)、过期、删除、更新事件
LRU有界映射:根据时间排序,超过容量限制的元素会被删除

public class MapExamples {

    public static void main(String[] args) throws IOException {
        // connects to 127.0.0.1:6379 by default
        RedissonClient redisson = Redisson.create();
        
        RMap<String, Integer> map =  redisson.getMap("myMap");
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        
        boolean contains = map.containsKey("a");
        
        Integer value = map.get("c");
        Integer updatedValue = map.addAndGet("a", 32);
        
        Integer valueSize = map.valueSize("c");
        
        Set<String> keys = new HashSet<String>();
        keys.add("a");
        keys.add("b");
        keys.add("c");
        Map<String, Integer> mapSlice = map.getAll(keys);
        
        // use read* methods to fetch all objects
        Set<String> allKeys = map.readAllKeySet();
        Collection<Integer> allValues = map.readAllValues();
        Set<Entry<String, Integer>> allEntries = map.readAllEntrySet();
        
        // use fast* methods when previous value is not required
        boolean isNewKey = map.fastPut("a", 100);
        boolean isNewKeyPut = map.fastPutIfAbsent("d", 33);
        long removedAmount = map.fastRemove("b");
        
        redisson.shutdown();
    }
    
}
映射持久化方式(缓存策略)

将映射中的数据持久化到外部存储服务的功能
主要场景:
1、作为业务和外部存储媒介之间的缓存
2、用来增加数据的持久性、增加已被驱逐的数据的寿命
3、用来缓存数据库、web服务或其他数据源的数据
Read-through策略:如果在映射中不存在,则通过Maploader对象加载
Write-through策略(数据同步写入):对映射数据的更改则会通过MapWriter写入到外部存储系统,然后更新redis里面的数据
Write-behind策略(数据异步写入):对映射数据的更改先写到redis,然后使用异步方式写入到外部存储

分布式锁和同步器

如果负责存储分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态,这时便会出现死锁。为了避免发生这种状况,提供了一个看门狗,它的作用是在Redisson实例被关闭之前,不断延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟。
分布式锁种类有:可重入锁(Reentrant Lock)、公平锁、联锁(MultiLock)
、红锁(RedLock)、 读写锁、信号量(Semaphore)、可过期性信号量(PermitExpirableSemaphore)、闭锁(CountDownLatch)

public class LockExamples {

    public static void main(String[] args) throws InterruptedException {
        // connects to 127.0.0.1:6379 by default
        RedissonClient redisson = Redisson.create();
        
        RLock lock = redisson.getLock("lock");
        lock.lock(2, TimeUnit.SECONDS);

        Thread t = new Thread() {
            public void run() {
                RLock lock1 = redisson.getLock("lock");
                lock1.lock();
                lock1.unlock();
            };
        };

        t.start();
        t.join();

        lock.unlock();
        
        redisson.shutdown();
    }
    
}

红锁

public class RedLockExamples {

    public static void main(String[] args) throws InterruptedException {
        // connects to 127.0.0.1:6379 by default
        RedissonClient client1 = Redisson.create();
        RedissonClient client2 = Redisson.create();
        
        RLock lock1 = client1.getLock("lock1");
        RLock lock2 = client1.getLock("lock2");
        RLock lock3 = client2.getLock("lock3");
        
        Thread t1 = new Thread() {
            public void run() {
                lock3.lock();
            };
        };
        t1.start();
        t1.join();
        
        Thread t = new Thread() {
            public void run() {
                RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
                lock.lock();
                
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                }
                lock.unlock();
            };
        };
        t.start();
        t.join(1000);

        lock3.forceUnlock();
        
        RedissonMultiLock lock = new RedissonRedLock(lock1, lock2, lock3);
        lock.lock();
        lock.unlock();

        client1.shutdown();
        client2.shutdown();
    }
    
}

分布式服务

分布式服务包括分布式远程服务(RRemoteService )、分布式实时对象服务(RLiveObjectService )、分布式执行服务(RExecutorService )、分布式调度任务服务(RScheduledExecutorService )、分布式映射归纳服务(MapReduce)
1、分布式远程服务:实现了java的RPC远程调用,可以通过共享接口执行另一个Redisson实例里的对象方法。
2、分布式实时对象(RLO):使用生成的代理类,将一个指定的普通java类的所有字段以及这些字段的操作(get set方法)全部映射到一个Redis Hash的数据结构。get和set方法被转义为hget和hset命令,从而使所有连接到同一个redis节点的客户端同时对一个指定对象操作。通过将这些值保存在一个像redis这样的远程共享的空间的过程,把这个对象强化成一个分布式对象。这个对象就叫RLO。
RLO使用方法:通过一系列注解@REntity(必选,类)、@RId(必选、主键字段)、@RIndex、@RObjectField、@RCascade(级联操作)
3、分布式执行服务:执行任务及取消任务

public class ExecutorServiceExamples {

    public static class RunnableTask implements Runnable, Serializable {

        @RInject
        RedissonClient redisson;

        @Override
        public void run() {
            RMap<String, String> map = redisson.getMap("myMap");
            map.put("5", "11");
        }
        
    }
    
    public static class CallableTask implements Callable<String>, Serializable {

        @RInject
        RedissonClient redisson;
        
        @Override
        public String call() throws Exception {
            RMap<String, String> map = redisson.getMap("myMap");
            map.put("1", "2");
            return map.get("3");
        }

    }
    
    public static void main(String[] args) {
        Config config = new Config();
        config.useClusterServers()
            .addNodeAddress("127.0.0.1:7001", "127.0.0.1:7002", "127.0.0.1:7003");
        
        RedissonClient redisson = Redisson.create(config);

        RedissonNodeConfig nodeConfig = new RedissonNodeConfig(config);
        nodeConfig.setExecutorServiceWorkers(Collections.singletonMap("myExecutor", 1));
        RedissonNode node = RedissonNode.create(nodeConfig);
        node.start();

        RExecutorService e = redisson.getExecutorService("myExecutor");
        e.execute(new RunnableTask());
        e.submit(new CallableTask());
        
        e.shutdown();
        node.shutdown();
    }
    
}

4、分布式调度任务服务:对计划任务的设定(可以通过CRON表达式)及去掉计划任务

public class SchedulerServiceExamples {

    public static class RunnableTask implements Runnable, Serializable {

        @RInject
        RedissonClient redisson;

        @Override
        public void run() {
            RMap<String, String> map = redisson.getMap("myMap");
            map.put("5", "11");
        }
        
    }
    
    public static class CallableTask implements Callable<String>, Serializable {

        @RInject
        RedissonClient redisson;
        
        @Override
        public String call() throws Exception {
            RMap<String, String> map = redisson.getMap("myMap");
            map.put("1", "2");
            return map.get("3");
        }

    }
    
    public static void main(String[] args) {
        Config config = new Config();
        config.useClusterServers()
            .addNodeAddress("127.0.0.1:7001", "127.0.0.1:7002", "127.0.0.1:7003");
        
        RedissonClient redisson = Redisson.create(config);

        RedissonNodeConfig nodeConfig = new RedissonNodeConfig(config);
        nodeConfig.setExecutorServiceWorkers(Collections.singletonMap("myExecutor", 5));
        RedissonNode node = RedissonNode.create(nodeConfig);
        node.start();

        RScheduledExecutorService e = redisson.getExecutorService("myExecutor");
        e.schedule(new RunnableTask(), 10, TimeUnit.SECONDS);
        e.schedule(new CallableTask(), 4, TimeUnit.MINUTES);

        e.schedule(new RunnableTask(), CronSchedule.of("10 0/5 * * * ?"));
        e.schedule(new RunnableTask(), CronSchedule.dailyAtHourAndMinute(10, 5));
        e.schedule(new RunnableTask(), CronSchedule.weeklyOnDayAndHourAndMinute(12, 4, Calendar.MONDAY, Calendar.FRIDAY));
        
        e.shutdown();
        node.shutdown();
    }
    
}

5、分布式映射归纳服务:通过映射归纳处理存储在Redis环境里的大量数据。示例代码单词统计

参考文档:

redisson

总结:

Reddisson提供的都是分布式对象,用来操作redis集群。
操作的数据分布在集群之中
分布式锁可以解决redis缓存击穿问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,677评论 6 524
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,772评论 3 408
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 173,108评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,378评论 1 303
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,394评论 6 403
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,807评论 1 315
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,127评论 3 432
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 41,136评论 0 281
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,693评论 1 328
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,703评论 3 349
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,810评论 1 357
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,400评论 5 352
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,130评论 3 341
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,532评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,707评论 1 278
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,412评论 3 383
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,892评论 2 368

推荐阅读更多精彩内容

  • 作者/翻译:张冬洪,Redis中国用户组主席什么是Redisson? Redisson是一个在Redis的基础上实...
    dd92c2f421e3阅读 5,358评论 1 1
  • 基于内存的NoSQL数据库。提供五种数据结构的存储。字符串、列表、集合、有序集合、散列表。Redis 支持很多特性...
    韩绝交阅读 705评论 0 1
  • 包含的重点内容:JAVA基础JVM 知识开源框架知识操作系统多线程TCP 与 HTTP架构设计与分布式算法数据库知...
    消失er阅读 4,341评论 1 10
  • redis集群分为服务端集群和客户端分片,redis3.0以上版本实现了集群机制,即服务端集群,3.0以下使用客户...
    hadoop_null阅读 1,597评论 0 6
  • TCP 与 HTTP http1.0 和 http1.1 有什么区别。 HTTP 1.0主要有以下几点变化: 请求...
    冷枫abc阅读 482评论 0 0