某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)

文章目录

    • 第二节 Redis分布式缓存
      • 3.2.1 redis数据结构和常用命令
        • Redis介绍
        • 通用命令(含测试)
        • 数据结构
          • String
          • List
          • Set
          • Sorted set
          • Hash
          • GEO
          • 5.0新增加Stream
        • 代码Demo
        • Jedis工具直连演示
        • pipeline批处理演示
        • GEO学习中,未完待续

第二节 Redis分布式缓存

3.2.1 redis数据结构和常用命令

Redis介绍

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第1张图片
官网下载
某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第2张图片

  • 支持各种语言
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第3张图片
  • 点击Download
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第4张图片
  • 往下面翻,查看安装步骤
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第5张图片

通用命令(含测试)

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第6张图片

  • 启动redis
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第7张图片

./bin/redis-cli官方提供的连接客户端的命令
不知道怎么用的话,可以执行./bin/redis-cli --help查看帮助
某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第8张图片

  • 执行命令./bin/redis-cli -h 127.0.0.1 -p 6379
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第9张图片

注意:
生产环境下禁止使用keys * 命令,因为它会遍历所有数据,数据量大的时候会极大影响性能

数据结构

String

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第10张图片
某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第11张图片

  • 简单应用举例
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第12张图片
  • 更多命令可自行查看官网命令介绍
    某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第13张图片
List

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第14张图片

Set

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第15张图片

Sorted set

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第16张图片

Hash

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第17张图片

GEO

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第18张图片

5.0新增加Stream

某易云课堂微专业--Java高级开发工程师--缓存中间件--Redis分布式缓存--学习笔记(十八)_第19张图片

代码Demo

  • xml配置
    
    
  • 注解配置

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@Profile("single")
// 开启spring cache注解功能
@EnableCaching
class SingleRedisAppConfig {
    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        System.out.println("使用单机版本");
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration("192.168.100.241", 6379));
    }

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 可以配置对象的转换规则,比如使用json格式对object进行存储。
        // Object --> 序列化 --> 二进制流 --> redis-server存储
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        return redisTemplate;
    }

    // 配置Spring Cache注解功能
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
        return cacheManager;
    }
}
  • Demo
import com.study.cache.redis.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
@Profile("single")
public class SingleExampleService {
    // 直接注入StringRedisTemplate,则代表每一个操作参数都是字符串
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 参数可以是任何对象,默认由JDK序列化
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 简单的缓存插入功能
     */
    public void setByCache(String userId, String userInfo) {
        stringRedisTemplate.opsForValue().set(userId, userInfo);
    }

    /**
     * 对象缓存功能
     */
    public User findUser(String userId) throws Exception {
        User user = null;
        // 1、 判定缓存中是否存在
        user = (User) redisTemplate.opsForValue().get(userId);
        if (user != null) {
            System.out.println("从缓存中读取到值:" + user);
            return user;
        }

        // TODO 2、不存在则读取数据库或者其他地方的值
        user = new User(userId, "张三");
        System.out.println("从数据库中读取到值:" + user);
        // 3、 同步存储value到缓存。
        redisTemplate.opsForValue().set(userId, user);
        return user;
    }

}
  • Test类
import com.study.cache.redis.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("single") // 设置profile
public class SingleTests {
    @Autowired
    SingleExampleService exampleService;

    // ------- spring redistemplate功能演示
    @Test
    public void setTest() {
        exampleService.setByCache("tony", "hahhhhh");
        exampleService.setByCache("a", "1");
        exampleService.setByCache("foo", "bar");
    }

    @Test
    public void getTest() throws Exception {
        User user = exampleService.findUser("tony");
        System.out.println(user);
    }


}

  • Spring Cache
import com.study.cache.redis.pojo.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
@Profile("single")
public class SpringCacheService {

    /**
     * springcache注解版本(官方大部分资料开始往springboot方向引导,实际上不用springboot,也是差不多的方式)
     */
    // value~单独的缓存前缀
    // key缓存key 可以用springEL表达式
    @Cacheable(cacheManager = "cacheManager", value = "cache-1", key = "#userId")
    public User findUserById(String userId) throws Exception {
        // 读取数据库
        User user = new User(userId, "张三");
        System.out.println("从数据库中读取到数据:" + user);
        return user;
    }

    @CacheEvict(cacheManager = "cacheManager", value = "cache-1", key = "#userId")
    public void deleteUserById(String userId) throws Exception {
        System.out.println("用户从数据库删除成功,请检查缓存是否清除~~" + userId);
    }

    // 如果数据库更新成功,更新redis缓存
    @CachePut(cacheManager = "cacheManager", value = "cache-1", key = "#user.userId", condition = "#result ne null")
    public User updateUser(User user) throws Exception {
        // 读取数据库
        System.out.println("数据库进行了更新,检查缓存是否一致");
        return user; // 返回最新内容,代表更新成功
    }
}
  • Spring Cache Test
import com.study.cache.redis.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("single") // 设置profile
public class SpringCacheTests {

    @Autowired
    SpringCacheService springCacheService;

    // ---------------spring cache注解演示
    // get
    @Test
    public void springCacheTest() throws Exception {
        User user = springCacheService.findUserById("tony");
        System.out.println(user);
    }

    // update
    @Test
    public void springCacheTest2() throws Exception {
        springCacheService.updateUser(new User("hhhhhhh-2", "tony"));
        User user = springCacheService.findUserById("tony");
        System.out.println(user);
    }

    // delete
    @Test
    public void springCacheTest3() throws Exception {
        springCacheService.deleteUserById("tony");
    }
}

Jedis工具直连演示

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("single") // 设置profile
public class JedisTests {

    // ------------------------ jedis 工具直连演示
    // jedis和redis命令名称匹配度最高,最为简洁,学习难度最低

    // 列表~ 集合数据存储~ java.util.List,java.util.Stack
    // 生产者消费者(简单MQ)
    @Test
    public void list() {
        Jedis jedis = new Jedis("192.168.100.241", 6379);
        // 插入数据1 --- 2 --- 3
        jedis.rpush("queue_1", "1");
        jedis.rpush("queue_1", "2", "3");

        List strings = jedis.lrange("queue_1", 0, -1);
        for (String string : strings) {
            System.out.println(string);
        }

        // 消费者线程简例
        while (true) {
            String item = jedis.lpop("queue_1");
            if (item == null) break;
            System.out.println(item);
        }

        jedis.close();
    }

    // 类似:在redis里面存储一个hashmap
    // 推荐的方式,无特殊需求是,一般的缓存都用这个
    @Test
    public void hashTest() {
        HashMap user = new HashMap<>();
        user.put("name", "tony");
        user.put("age", 18);
        user.put("userId", 10001);
        System.out.println(user);

        Jedis jedis = new Jedis("192.168.100.241", 6379);
        jedis.hset("user_10001", "name", "tony");
        jedis.hset("user_10001", "age", "18");
        jedis.hset("user_10001", "userId", "10001");
        System.out.println("redis版本~~~~~");
        // jedis.hget("user_10001", "name");
        System.out.println(jedis.hgetAll("user_10001"));
        jedis.close();
    }

    // 用set实现(交集 并集)
    // 交集示例: 共同关注的好友
    // 并集示例:
    @Test
    public void setTest() {
        // 取出两个人共同关注的好友
        Jedis jedis = new Jedis("192.168.100.241", 6379);
        // 每个人维护一个set
        jedis.sadd("user_A", "userC", "userD", "userE");
        jedis.sadd("user_B", "userC", "userE", "userF");
        // 取出共同关注
        Set sinter = jedis.sinter("user_A", "user_B");
        System.out.println(sinter);

        // 检索给某一个帖子点赞/转发的
        jedis.sadd("trs_tp_1001", "userC", "userD", "userE");
        jedis.sadd("star_tp_1001", "userE", "userF");
        // 取出共同人群
        Set union = jedis.sunion("star_tp_1001", "trs_tp_1001");
        System.out.println(union);

        jedis.close();
    }

    // 游戏排行榜
    @Test
    public void zsetTest() {
        Jedis jedis = new Jedis("192.168.100.241", 6379);
        String ranksKeyName = "exam_rank";
        jedis.zadd(ranksKeyName, 100.0, "tony");
        jedis.zadd(ranksKeyName, 82.0, "allen");
        jedis.zadd(ranksKeyName, 90, "mengmeng");
        jedis.zadd(ranksKeyName, 96, "netease");
        jedis.zadd(ranksKeyName, 89, "ali");

        Set stringSet = jedis.zrevrange(ranksKeyName, 0, 2);
        System.out.println("返回前三名:");
        for (String s : stringSet) {
            System.out.println(s);
        }

        Long zcount = jedis.zcount(ranksKeyName, 85, 100);
        System.out.println("超过85分的数量 " + zcount);

        jedis.close();
    }
}

pipeline批处理演示

  • config

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@Profile("pipeline")
class PipelineRedisAppConfig {

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        System.out.println("使用单机版本");
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration("192.168.100.241", 6379));
    }

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 可以配置对象的转换规则,比如使用json格式对object进行存储。
        // Object --> 序列化 --> 二进制流 --> redis-server存储
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        return redisTemplate;
    }
}
  • test
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("pipeline") // 设置profile
public class PipelineTests {
    @Autowired
    RedisTemplate redisTemplate;

    @Test
    public void test1() throws InterruptedException {
        // 普通模式和pipeline模式
        long time = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            redisTemplate.opsForList().leftPush("queue_1", i);
        }
        System.out.println("操作完毕:" + redisTemplate.opsForList().size("queue_1"));
        System.out.println("普通模式一万次操作耗时:" + (System.currentTimeMillis() - time));

        time = System.currentTimeMillis();
        redisTemplate.executePipelined(new RedisCallback() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                for (int i = 0; i < 10000; i++) {
                    connection.lPush("queue_2".getBytes(), String.valueOf(i).getBytes());
                }
                return null;
            }
        });
        System.out.println("操作完毕:" + redisTemplate.opsForList().size("queue_2"));
        System.out.println("pipeline一万次操作耗时:" + (System.currentTimeMillis() - time));


    }
}

GEO学习中,未完待续

你可能感兴趣的:(Java高级开发工程师)