Redis的Java客户端学习总结

使用Redis神奇的HyperLogLog做UV统计 本文介绍Redis神奇的数据结构HyperLogLog,它可以用很小的内存,统计很多数据的基数(不重复的元素个数),并利用此特性来统计UV/DAU/MAU,具有高性能,占用内存小特点。 阅读详情

—————————<<

Jedis

以 Redis 命令作为方法名称,学习成本低,简单实用。
但是 Jedis 实例是线程不安全的,多线程环境下需要基于连接池来使用。

  1. 依赖
<!--jedis-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>

  1. 简单案例
import redis.clients.jedis.Jedis;

/**
 * 
 * @author chengjiang
 */
public class DemoJedis {

    public static void main(String[] args) {

        // 1、建立连接
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        // 2、设置密码
//        jedis.auth("密码");

        // 3、选择库
        jedis.select(0);

        // 存入数据
        String result = jedis.set("name", "张三");
        System.out.println("result = " + result);
        // result = OK

        // 获取数据
        String name = jedis.get("name");
        System.out.println(name);
        // 张三

    }
}

—————————<<

Lettuce

Lettuce 是基于 Netty 实现的,支持同步、异步和响应式编程方式,并且是线程安全的。
支持 Redis 的哨兵模式、集群模式和管道模式。
它是一种可扩展的、线程安全的 Redis 高级客户端。
从 Spring Boot 2.x 开始, Lettuce 已取代 Jedis 成为SpringBoot 默认的 Redis 客户端。

  1. 依赖
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>5.1.8.RELEASE</version>
</dependency>
  1. 简单案例
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.SetArgs;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import java.time.Duration;
import java.time.temporal.ChronoUnit;

/**
 * @author chengjiang
 */
public class DemoLettuce {

    public static void main(String[] args) {

        // <1> 创建单机连接的连接信息
        RedisURI redisUri = RedisURI.builder()
                .withHost("localhost")
                .withPort(6379)
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();

        // <2> 创建客户端
        RedisClient redisClient = RedisClient.create(redisUri);

        // <3> 创建线程安全的连接
        StatefulRedisConnection<String, String> connection = redisClient.connect();

        // <4> 创建同步命令
        RedisCommands<String, String> redisCommands = connection.sync();

        SetArgs setArgs = SetArgs.Builder.nx().ex(5);
        String result = redisCommands.set("name33", "李四", setArgs);
        System.out.println("result = " + result);
        // result = OK

        String result2 = redisCommands.get("name33");
        System.out.println("result2 = " + result2);
        // result2 = 李四

        // <5> 关闭连接
        connection.close();

        // <6> 关闭客户端
        redisClient.shutdown();
    }
}

—————————<<

SpringDataRedis

SpringDataRedis 是 Spring中数据操作模块 SpringData 中的一员,它提供了对不同Redis客户端的整合(Lettuce和Jedis)
,提供了 RedisTemplate 统一的API来操作Redis。

  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化与反序列化
  • 支持基于Redis的JDKCollection实现
  1. 依赖
<!--Redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 案例
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * spring redis 工具类
 *
 * @author chengjiang
 */
@Component
public class RedisService {

    @Resource
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 自增缓存
     * key在Redis中不存在,redis中会创建这个key,并生成一个值,值为1
     * key在Redis中存在,那么就会在当前数值的基础上再加1后保存
     *
     * @param key      缓存的键值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public Long increment(final String key, final Long timeout, final TimeUnit timeUnit) {
        Long increment = increment(key);
        expire(key, timeout, timeUnit);
        return increment;
    }

    /**
     * 自减缓存
     *
     * @param key      缓存的键值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public Long decrement(final String key, final Long timeout, final TimeUnit timeUnit) {
        Long increment = decrement(key);
        expire(key, timeout, timeUnit);
        return increment;
    }

    /**
     * 自增缓存
     * key在Redis中不存在,redis中会创建这个key,并生成一个值,值为1
     * key在Redis中存在,那么就会在当前数值的基础上再加1后保存
     *
     * @param key      缓存的键值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public Long increment(final String key, long delta, final Long timeout, final TimeUnit timeUnit) {
        Long increment = increment(key, delta);
        expire(key, timeout, timeUnit);
        return increment;
    }

    /**
     * 自增缓存
     * key在Redis中不存在,redis中会创建这个key,并生成一个值,值为1
     * key在Redis中存在,那么就会在当前数值的基础上再加1后保存
     *
     * @param key 缓存的键值
     */
    public Long increment(final String key) {
        return redisTemplate.boundValueOps(key).increment();
    }

    /**
     * 自增缓存
     * key在Redis中不存在,redis中会创建这个key,并生成一个值,值为1
     * key在Redis中存在,那么就会在当前数值的基础上再加1后保存
     *
     * @param key 缓存的键值
     */
    public Long increment(final String key, long delta) {
        return redisTemplate.boundValueOps(key).increment(delta);
    }

    /**
     * 自减缓存
     *
     * @param key 缓存的键值
     */
    public Long decrement(final String key, long delta) {
        return redisTemplate.boundValueOps(key).decrement(delta);
    }

    /**
     * 自减缓存
     *
     * @param key 缓存的键值
     */
    public Long decrement(final String key) {
        return redisTemplate.boundValueOps(key).decrement();
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout) {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 定时设置有效时间
     *
     * @param key  Redis键
     * @param date 超时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expireAt(final String key, final Date date) {
        return redisTemplate.expireAt(key, date);
    }

    /**
     * 获取有效时间
     *
     * @param key Redis键
     * @return 有效时间
     */
    public long getExpire(final String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 获取有效时间
     *
     * @param key Redis键
     * @return 有效时间
     */
    public long getExpire(final String key, final TimeUnit timeUnit) {
        return redisTemplate.getExpire(key, timeUnit);
    }

    /**
     * 判断 key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(final String key) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public boolean deleteObject(final String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 删除Region
     *
     * @param region
     */
    public long deleteRegion(final String region) {
        Set keys = redisTemplate.keys(region + "*");
        return redisTemplate.delete(keys);
    }

    /**
     * 删除集合对象
     *
     * @param collection 多个对象
     * @return
     */
    public long deleteObject(final Collection collection) {
        return redisTemplate.delete(collection);
    }

    /**
     * 缓存List数据
     *
     * @param key      缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */
    public <T> long setCacheList(final String key, final List<T> dataList) {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    }

    /**
     * 缓存List数据
     *
     * @param key      缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */
    public <T> long setCacheList(final String key, final List<T> dataList, final long timeout, final TimeUnit unit) {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        redisTemplate.expire(key, timeout, unit);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public <T> List<T> getCacheList(final String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 缓存Set
     *
     * @param key     缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext()) {
            setOperation.add(it.next());
        }
        return setOperation;
    }

    /**
     * 缓存Set
     *
     * @param key     缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final T... dataSet) {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        setOperation.add(dataSet);
        return setOperation;
    }

    /**
     * set中移除指定元素
     *
     * @param key
     * @param dataSet
     * @return
     */
    public <T> Long removeSet(final String key, final Set<T> dataSet) {
        return redisTemplate.opsForSet().remove(key, dataSet);
    }

    public <T> Long removeSet(final String key, T... dataSet) {
        return redisTemplate.opsForSet().remove(key, dataSet);
    }

    /**
     * set 出栈
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> T popSet(final String key) {
        return (T) redisTemplate.opsForSet().pop(key);
    }

    /**
     * 向key对应的value值中批量添加值,可以是集合、数组、多参数
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> T addSet(final String key, final T value) {
        return (T) redisTemplate.opsForSet().add(key, value);
    }

    /**
     * 获取key对应的值的长度
     *
     * @param key
     * @return
     */
    public Long countBySet(final String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * set 出栈
     *
     * @param key
     * @return
     */
    public Long countByList(final String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 检查给定的元素是否在Set变量中
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean isMember(final String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(final String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(final String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 往Hash中存入数据
     *
     * @param key   Redis键
     * @param hKey  Hash键
     * @param value 值
     */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
        redisTemplate.opsForHash().put(key, hKey, value);
    }

    /**
     * 获取Hash中的数据
     *
     * @param key  Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public <T> T getCacheMapValue(final String key, final String hKey) {
        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    }

    /**
     * 获取多个Hash中的数据
     *
     * @param key   Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(final String pattern) {
        return redisTemplate.keys(pattern);
    }

}

—————————<<

Redisson

Redisson 是一个在 Redis 的功能基础上实现的 Java 驻内存数据网格客户端。实现了分布式和可扩展的 Java 数据结构,提供很多分布式相关操作服务,例如分布式锁,分布式集合,可通过 Redis 支持延迟队列。

依赖

<!--redisSon-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
</dependency>

yml配置

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 
    

案例:

import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.Test;
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.codec.SerializationCodec;
import org.redisson.config.Config;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author chengjiang
 */
public class DemoRedisson {

    /**
     * 通用对象桶,可以用来存放任类型的对象
     */
    @Test
    public void RedissonBucket() {
        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作对象桶来存储对象(同步)
        RBucket<Object> bucket = redissonClient.getBucket("redisson-bucket");

        //设置值为victory,过期时间为3小时
        bucket.set("测试一下看看", 30, TimeUnit.HOURS);

        Object value = bucket.get();
        System.out.println("value----" + value);
        // value----测试一下看看

        //通过key取value值
        Object name = redissonClient.getBucket("name444").get();
        System.out.println("name----" + name);
        // name----测试一下看看

        // 关闭客户端
        redissonClient.shutdown();
    }

    /**
     * 二进制流
     * 提供了InputStream接口和OutputStream接口的实现
     */
    @Test
    public void RedissonStream() throws IOException {
        // 创建Redisson客户端 
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作流来存储对象 
        RBinaryStream stream = redissonClient.getBinaryStream("redisson-stream");

        // 写入数据方式一
        stream.set("你好,".getBytes());

        // 写入数据方式一
        OutputStream outputStream = stream.getOutputStream();
        outputStream.write("测试一下看看".getBytes());

        // 读取数据
        InputStream inputStream = stream.getInputStream();
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int length;
        while ((length = inputStream.read(bytes)) != -1) {
            result.write(bytes, 0, length);
        }
        System.out.println(result.toString());

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * Redisson操作list
     */
    @Test
    public void list() {

        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作list 
        RList<String> list = redissonClient.getList("redisson-list");
        list.add("victory1");
        list.add("victory2");

        //取值
        List<String> list1 = list.readAll();
        System.out.println("list1----" + JSON.toJSONString(list1));
        // list1----["victory1","victory2"]

        //移除索引0位置元素
        list.remove(0);

        //取值
        List<String> list2 = list.readAll();
        System.out.println("list2----" + JSON.toJSONString(list2));
        // list2----["victory2"]

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * set
     * Redisson操作set
     */
    @Test
    public void set() {

        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作list 
        RSet<Object> set = redissonClient.getSet("redisson-set");
        set.add("victory1");
        set.add("victory2");

        //通过key取value值
        Set<Object> set1 = redissonClient.getSet("redisson-set");
        System.out.println("set1 -- " + set1);
        // set1 -- [victory2, victory1]

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * map
     * Redisson操作map
     * Redisson将Redis中的字符串数据结构封装成了RMap,就是原本redis中的string类型
     */
    @Test
    public void map() {

        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作list 
        RMap<Object, Object> map = redissonClient.getMap("redisson-map");
        map.put("name1", "victory1");
        map.put("name2", "victory2");

        //通过key取value值
        Object o = redissonClient.getMap("redisson-map").get("name1");
        System.out.println(o);

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * 队列
     * Redisson操作queue
     */
    @Test
    public void queue() {

        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作queue 
        RQueue<String> queue = redissonClient.getQueue("redisson-queue");

        //存值
        queue.add("victory1");
        queue.add("victory2");

        //取值
        String item = queue.poll();
        System.out.println(item);

        //
        RQueue<Object> queue1 = redissonClient.getQueue("redisson-queue");
        System.out.println(queue1);

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * 阻塞队列
     * Redisson操作blockingDeque
     */
    @Test
    public void blockingDeque() throws InterruptedException {

        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        //阻塞队列
        RBlockingQueue<Object> blockingQueue = redissonClient.getBlockingQueue("redisson-blockingDeque");

        //延迟队列
        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);

        delayedQueue.offer("阻塞消息阻塞消息阻塞消息阻塞消息", 30, TimeUnit.SECONDS);

        // 获取消息
        RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque("redisson-blockingDeque");
        Object msg = blockingDeque.take();

        System.out.println("msg = " + msg);

    }

    /**
     * 限流器
     * Redisson操作rateLimiter
     */
    @Test
    public void rateLimiter() throws InterruptedException {

        // 创建Redisson客户端 
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作rateLimiter 
        RRateLimiter rateLimiter = redissonClient.getRateLimiter("redisson-rateLimiter");

        // 创建限流器,最大流速:每1秒钟产生20个令牌
        rateLimiter.trySetRate(RateType.OVERALL, 20, 10, RateIntervalUnit.SECONDS);

        long l2 = System.currentTimeMillis();
        for (int i = 0; i < 22; i++) {

            rateLimiter.acquire(1);

            long l = System.currentTimeMillis();
            System.out.println("----------" + i + " = " + (l - l2));
            // ----------18 = 0
            // ----------19 = 1
            // ----------20 = 10008

            l2 = l;
        }

        // 等待执行完成,不设置等待可能出现还未执行完成客户端就关闭的情况
        Thread.sleep(2000);

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * 可重入锁
     * Redisson操作RLock
     */
    @Test
    public void lock() throws InterruptedException {
        // 创建Redisson客户端 
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作lock 
        RLock lock = redissonClient.getLock("redisson-lock");

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                lock.lock();

                try {
                    System.out.println(Thread.currentThread().getName() + "---" + System.currentTimeMillis() + "---" + "获取了锁");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }).start();
        }

        // 等待执行完成,不设置等待可能出现还未执行完成客户端就关闭的情况
        Thread.sleep(30000);

        // 关闭客户端 
        redissonClient.shutdown();
    }

    /**
     * 发布订阅操作
     * Redisson操作RTopic执行发布订阅操作
     **/
    @Test
    public void topicPublisherAndSubscriber() throws InterruptedException {

        // 创建Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作topic执行发布操作
        RTopic topic1 = redissonClient.getTopic("redisson-topic", new SerializationCodec());
//        topic1.publish(new Message(1L, "victory", 18));
        topic1.publish("消息消息消息消息消息消息");

        // 操作topic执行订阅操作
        Thread.sleep(5000);
        RedissonClient redissonClient1 = Redisson.create(config);
        RTopic topic = redissonClient1.getTopic("redisson-topic", new SerializationCodec());
        topic.addListener(String.class, (channel, msg) -> {
            System.out.println("Redisson接收到消息" + msg);
        });

        Thread.sleep(10000);

        // 关闭客户端 
        redissonClient.shutdown();
        redissonClient1.shutdown();
    }


    /**
     * Redisson利用Redis实现了Java分布式布隆过滤器(Bloom Filter)
     * 作用:在缓存层前添加布隆过滤器,常用于高并发场景下应对缓存穿透问题
     * 布隆过滤器是一个非常长的二进制向量和一系列随机哈希函数的组合,可用于检索一个元素是否存在;
     */
    @Test
    public void bloomFilter() {

        // 创建Redisson客户端 
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redissonClient = Redisson.create(config);

        // 操作布隆过滤器
        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("redisson-bloom-filter");

        // 初始化布隆过滤器,初始化预期插入的数据量为200,期望误差率为0.01
        bloomFilter.tryInit(200, 0.01);

        //插入数据
        bloomFilter.add("qwe");
        bloomFilter.add("asd");
        bloomFilter.add("zxc");

        //判断是否包含
        boolean victory = bloomFilter.contains("qwe");
        boolean forward = bloomFilter.contains("cvb");

        System.out.println(victory);
        //true

        System.out.println(forward);
        //false

        // 关闭客户端 
        redissonClient.shutdown();
    }

}

深入学习 Redis - 基于 Jedis 通过 Java 客户端操作 Redis 和 Redis 集群 我们在本地 windows 主机上,使用 xshell 连接远程服务器,主要就是通过 ssh 协议(默认走 22 端口)实现通信的,他有一个很重要的特性,就是支持端口转发!我们只需要配置 ssh 程序监听本地端口,映射到云服务器的端口,就可以实现通过 windows 主机,访问云服务器的 6379 端口.Ps:一个优秀的库,一定是非常容易上手的,因此接下来介绍的操作,不会覆盖到所有指令,会挑选出一些重要 / 代表性的命令,来进行演示~Ps:当配置了端口准发后,一定要断开之前的连接,重新连接才能生效. 阅读详情

相关推荐

用朴素贝叶斯分类模型判断病人是否感染幽门螺杆菌(Python实现)

朴素贝叶斯,Python

weixin_56529327的博客 1160

时间颗粒度

序 、昨天突然的大雨 ,来的很突然 。 很早之前 ,网络上流传一张王健林的行程表。这位62岁的中国首富,早上4点起床健身,然后飞行6000公里,出现在两个国家、三个城市,最终,晚上7点赶回办公室,继续加班。 这张行程表出现后,网友们纷纷表示,受到了10000点的伤害。最可怕的事情看来真的是:比我成功N倍的人,居然惨无人道地比我更努力!这世界,到底还给不给我们这些年轻人机会啊! 在这里涉及到一个概念 ,时间颗粒度 。时间颗粒度,就是一个人安排时间的基本单位。根据行程表,...

Super 含 的博客 1947

相机标定原理与张氏标定法

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

heeweii的博客 2280

Redis缓存及缓存粒度

什么是Redis缓存? 缓存就是为了更快的获取一些东西,而把这些东西从一个地方暂时或者永久的存储到另一个方便快捷获取的地方的机制。 为什么要用缓存? 现在互联网应用(网站或App)的整体流程,大致可以概括为用户请求从界面(浏览器或App界面)到网络转发、应用服务再到存储(数据库或文件系统),然后返回到界面呈现内容。 随着互联网的普及,内容信息越来越复杂,用户数和访问量越来越大,我们的应用需要支撑更多的并发量,同时我们的应用服务器和数据库服务器所做的计算也越来越多。但是往往我们的应用服务器资源是有限的,且技术

@日月空@的博客 1687

突发环境事件怎么模拟?用Python+GIS实现高斯烟团模型(附完整代码)

本文详细介绍了如何利用Python与GIS技术实现高斯烟团模型,用于模拟化工泄漏等突发环境事件的动态扩散过程。通过核心原理讲解、参数快速获取方案、Python代码实现及GIS可视化集成,为环境应急人员提供了一套完整的解决方案。特别适合危险品运输事故等瞬态污染场景的应急决策支持。

weixin_33692284的博客 485

从零实现机械臂抓取仿真:用MoveIt+Gazebo完成物体pick&place全流程

本文详细介绍了如何使用ROS的MoveIt框架与Gazebo仿真环境,从零构建机械臂抓取仿真系统。涵盖环境搭建、MoveIt配置、Gazebo集成、抓取动作实现等全流程,帮助开发者掌握机械臂控制的核心技术,实现高效的pick&place任务。

weixin_29250403的博客 476

Redis 持久化:RDB,AOF介绍

目录 一.什么是持久化 二.RDB 1.1 优点 1.2 缺点 三.AOF(append only file) 2.1 优点 2.2 缺点 四. 持久化选择策略 一.什么是持久化 持久化就是将内存中的数据定时的保存到磁盘中的过程。持久化是Redis高可用中比较重要的一个环节,因为Redis数据在内存的特性,持久化必须得有,不然服务器宕机会导致数据全丢。 RDB:RDB ...

sinat_35566306的博客 459

STM32串口DMA双缓冲机制实战:提升数据传输效率的终极方案

本文深入解析了STM32串口DMA双缓冲机制的核心原理与实战配置。通过对比传统中断方式,阐述了双缓冲如何实现数据接收与处理的“无缝接力”,从而在工业传感器数据采集等高负载场景下,将CPU占用率降至极低水平并彻底避免数据丢失。文章提供了基于标准外设库的详细配置步骤、中断处理逻辑及性能实测数据,是提升嵌入式系统串口通信效率和可靠性的终极方案。

weixin_29192365的博客 79

java(SpringBoot)中操作Redis的两种方式

之前我们介绍过了redis的五中基本类型以及在可视化界面进行操作,那么在开发中(在代码中)我们通常使用,jedis进行操作redis,要是springboot 项目,我们通常使用redisTemplte进行操作首先将redis启动。

从零开始的博客 2557

从Gitee上部署视觉工程到Linux虚拟机

(使用SVM来识别装甲板的编号,此处手机上的图片中只有灯条没有数字,SVM无法识别出编号。这两行代码的意义是,当SVM识别不出或者识别不到编号时,把装甲板的编号默认为2号。找到自瞄程序中,数字识别类下的这两行代码,把注释去掉。这样,每次打开新的终端时,环境变量都会自动设置。(2)查看虚拟机设置选项,检查虚拟机USB接口是否为3.0及以上的接口。如果不是,要更改好。这样,每次打开新的终端时,环境变量都会自动设置。后,每次打开终端时自动设置这些环境变量,你可以将。打开第一个终端,用来挂ROS的内核启动页面。

2301_81035291的博客 1520

Vivado新手必看:5分钟搞定FPGA程序固化到Flash(附MCS文件生成全流程)

本文为FPGA新手详细解析了如何将程序固化到Flash存储器的完整流程。核心在于理解SRAM工艺FPGA断电易失的特性,并利用Vivado工具将比特流文件转换为Flash可识别的MCS文件。文章重点拆解了生成MCS文件的关键配置步骤、硬件连接要点,以及通过JTAG烧写Flash的实战操作,并提供了常见启动失败问题的排查清单,帮助开发者实现设计从调试到产品部署的关键跨越。

weixin_29230901的博客 351

[数据库] Redis学习笔记(二):Redis Java客户端(Jedis/SpringDataRedis)

redis的Java客户端

東木的博客 1012

IGS精密星历高效获取与解析指南

本文详细介绍了IGS精密星历在高精度定位中的核心作用,对比了IGS Final、IGR和IGU等不同产品的精度与时效性差异。指南提供了从武汉大学、NASA CDDIS等数据中心高效下载数据的实战方法,并深入解析了SP3文件格式,帮助用户掌握精密星历的获取、解析与自动化处理技巧,以支持厘米级定位应用。

garlic的博客 838

【从零开始学习Redis】Redis的Java客户端

本文介绍了Redis在Java中的三种常用客户端:Jedis、Lettuce和Redisson。Jedis简单易用但线程不安全,需配合连接池使用;Lettuce基于Netty实现,支持多种编程模式且线程安全;Redisson提供分布式数据结构支持。文章详细演示了Jedis的基本使用方法,包括连接配置、字符串和哈希操作,以及通过JedisPool实现连接池管理。最后介绍了SpringDataRedis框架,它整合了多种Redis客户端,提供统一的RedisTemplate API,支持多种数据序列化方式,并给

朝碧海而暮苍梧 484

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【Redis学习路|第三篇】Redis的Java客户端

本章内容介绍了Redis的Java客户端,并简单介绍了客户端的选择与Jedis客户端,以及详细分析了解了SpringDataRedis客户端及内部StringRedisTemplate的使用。

超级苦力怕的博客 1196

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

国人最新开源了一款超好用的Redis客户端,详细的Java学习指南

前言 这期我想写很久了,但是因为时间的原因一直拖到了现在,我以为一两天就写完了,结果从构思到整理资料,再到写出来用了差不多一周的时间吧。 你们也知道作者一直都是创作鬼才来的,所以我肯定不会一本正经的写,我想了好几个切入点,最后决定用一个完整的电商系统作为切入点,带着大家看看,我们需要学些啥,我甚至还收集配套视频和资料,暖男石锤啊,这期是呕心沥血之作,不要白嫖了。 java基础 1.1java的8种基本数据类型装箱拆箱 1.2重写重载封装继承多态 1.3 Stack Queue 1.7 Concurrent包

m0_57286472的博客 162

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

初识redis:学习Java客户端

详细的介绍了常用的redis命令在Java客户端的使用方法,快来看看吧~

m0_62319039的博客 1191

redis个人学习笔记 八:Redis的Java客户端Jedis简单使用

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此文是我看尚硅谷教学视频后的个人的redis学习笔记,每一张截图都是我亲自敲后截图放在笔记中的,粘贴在博客上可能会有点点模糊,若有错误或不足,还望各位大神多多指正! 10 Redis的Java客户端Jedis简单使用 10.1 Jedis所需要的jar包 &nbsp;&nbsp;&nbsp;&nbsp;&nb...

蓝宁飞的博客 381

从零开始学习Redis(二):Redis的Java客户端

在 Java 生态中,Redis 客户端有多种选择,不同客户端在性能、功能、易用性上各有侧重。:以Redis命令作为方法名称,简单实用。但Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用,适用于小型单体应用 / 快速验证:Lettuce是基于Netty(一种高性能的网络编程框架) 实现的,支持同步,异步和响应式编程方式,并且线程安全。支持Redis的哨兵模式,集群模式,管道模式。适用于高并发微服务 / 异步场景:Redisson是一个。

2301_80293990的博客 735

【Redis】学习(3)Redis的Java客户端

摘要:本文介绍了两种Java操作Redis的客户端工具。Jedis客户端使用步骤包括引入依赖、创建连接、执行命令和释放资源,推荐使用Jedis连接池提高性能。SpringDataRedis是Spring整合Redis的模块,提供RedisTemplate统一API,支持多种数据结构和序列化方式。通过配置类可自定义序列化方案,将Key设为String类型,Value设为JSON格式,解决了JDK默认序列化可读性差的问题。文章详细说明了两种客户件的快速入门方法和关键配置要点。

c4531894的博客 390

Redis 学习笔记 2:Java 客户端

Spring 对 Jedis 和 lettuce 进行了封装,spring-data-redis 提供统一的 API 进行操作。

梦幻天空 1380

Redis学习路线(3)——Redis的Java客户端

介绍了Redis的Java客户端,主要使用了SpringDataRedis,它整合了Jedis和Lettuce,也介绍了关于Redis客户端的序列化和反序列化的相关知识和使用

Zain_horse的博客 500

Redis学习记录:Java客户端

Jedis封装的API方法与Redis命令高度重合,直接使用即可。创建Maven项目,pom文件里引入Jedis依赖。Jedis对象本身线程不安全,一般通过连接池获取。利用try-with-resource改进一下。继续改进可以封装成接口,通过调用实现类来操作。Redis默认不支持远程连接,需要手动开启。修改配置文件 redis.conf。

yueyue0609的博客 364

【JavaWeb后端学习笔记】Redis常用命令以及Java客户端操作Redis

redis是基于内存的key-value结构的数据库。

wrjwww的博客 1379

redis学习笔记之十七:Redis的Java客户端

n Redis官方推荐的Java客户端是jedis 网址:https://github.com/xetorthio/jedis n 构建开发环境,在Maven中添加 &lt;dependency&gt; &lt;groupId&gt;redis.clients&lt;/groupId&gt; &lt;artifactId&gt;jedis&lt;/artifactId&gt; &lt;versio...

u010800970的专栏 270

redis学习笔记,Redis的Java客户端Jedis

Jedis常用操作 测试连通性 5+1: package com.atguigu.redis.test; import java.util.*; import redis.clients.jedis.Jedis; public class Test02 { public static void main(String[] args) { Jed...

qq_28527469的博客 202
上一篇: Java 8 函数式接口学习总结
下一篇: H2数据库学习总结
star_falling
博客等级 码龄11年 287粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值