redis 基础概述与使用

一. redis 概述

  1. redis 基于内存的单线程非关系型数据库,每秒支持十万并发
  2. 架构模式: 单机版, 主从复制,哨兵模式,分片集群
  3. 使用场景: 热点数据缓存,生成令牌,网站计数器,通过redis实现接口幂,存储验证码,分布式锁,生成分布式ID

redis 主从同步执行流程

在集群环境中多个redis 分为master主库与Salve从库,当Salve启动后会连接到master主库,并发送一个sync命令,master接收到该命令后台启动一个进程,收集接收到的操作数据指令缓存为快照文件,当缓存完毕后,将这个文件发送给所有连接到该master的Salve从库,Salve将文件接收保存到磁盘上,然后加载到内存中,后续master主库接收到的修改数据指令都会通过这个后台进程发送给Salve

redis 淘汰策略

在这里插入图片描述

SpringBoot 整合 redis

  1. 引入 resid 依赖
	<!-- SpringBoot对Redis支持 -->
	<dependency>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-data-redis</artifactId>
	</dependency>
	<!--如果使用jedis操作redis数据的话添加这个依赖 -->
	<dependency>
	    <groupId>redis.clients</groupId>
	    <artifactId>jedis</artifactId>
	    <version>2.9.0</version>
	</dependency>
  1. yml 文件中配置redis连接
    单机版:
spring:
  redis:
	#设置数据存放在redis的哪个库中,此处为默认的0库
    database: 0
    host: 132.232.44.194
    port: 6379
    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000

集群版

spring:
  redis:
    database: 0
#集群版本不需这些设置(否则会走单机连接)
#    host: 132.232.44.194
#    port: 6379
#    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000
    cluster:
      nodes:
        - 192.168.212.149:9001
        - 192.168.212.149:9002
        - 192.168.212.149:9003
        - 192.168.212.149:9004
        - 192.168.212.149:9005
        - 192.168.212.149:9006
  1. 代码中使用 StringRedisTemplate 或 RedisTemplate 操作redis
	@Autowired
    private StringRedisTemplate stringRedisTemplate;
	//StringRedisTemplate
	//StringRedisTemplate.opsForValue().* //操作String字符串类型
	//StringRedisTemplate.delete(key/collection) //根据key/keys删除
	//StringRedisTemplate.opsForList().*  //操作List类型
	//StringRedisTemplate.opsForHash().*  //操作Hash类型
	//StringRedisTemplate.opsForSet().*  //操作set类型
	//StringRedisTemplate.opsForZSet().*  //操作有序set


	 @Autowired
    private RedisTemplate<String, String> redisTemplate;
	/* RedisTemplate对象,可以理解为一个map集合对象,通过这个对象操作redis中的各种类型数据,
    * redisTemplate.opsForValue() -> ValueOperations<String, Object>;// 操作字符串
    * redisTemplate.opsForHash() -> HashOperations<String, String, String>;// 操作 hash
    * redisTemplate.opsForList() -> ListOperations<String, Object>;// 操作 list
    * redisTemplate.opsForSet() -> SetOperations<String, Object>;// 操作 set
    * redisTemplate.opsForZSet() -> ZSetOperations<String, Object>;// 操作 SortedSet */

StringRedisTemplate 与 RedisTemplate

  • StringRedisTemplate 继承了 RedisTemplate 但是连着操作的数据不是共通的,StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据
  • RedisTemplate 使用JdkSerializationRedisSerializer 序列化机制,存入数据会将数据先序列化成字节数组然后在存入Redis数据库。
  • StringRedisTemplate使用的是StringRedisSerializer
  • 推荐: 存储数据是字符串类型的时候,就算存储对象也是将对象转换为JSON串,使用StringRedisTemplate即可。如果存储的数据是复杂的对象类型,取出的时候又不想做数据转换,直接从Redis里面取出一个对象,使用RedisTemplate
  • RedisTemplate 中存取数据都是字节数组。当redis中存入的数据是可读形式而非字节数组时,使用redisTemplate取值的时候会无法获取导出数据,获得的值为null。可以使用 StringRedisTemplate 试试
    在这里插入图片描述

redis 支持事物控制与锁

  1. 以代码举例(在实际项目中可以通过拦截器,操作redis的事物)
    在这里插入图片描述
  2. redis支持锁,在使用锁
    在这里插入图片描述

redis 设置key失效

调用expire(),方法,指定哪个key,指定存活时间,时间单位

	//设置redis中指定key的失效时间(毫秒)
    public boolean setTime(String key, Long time){
        if(null != key || time !=0){
           return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
        }else {
            return false;
        }
    }

redis 指定库

redis 默认有16个库,从0开始,默认使用0库,可以通过配置修改库的个数,可以手动指定选择哪个库

	@Test
    public void test2() {
        //1.通过jedisPool获取连接
        Jedis conn = jedisPool.getResource();
        //2.通过stringRedisTemplate获取连接
        JedisConnectionFactory factory = (JedisConnectionFactory) stringRedisTemplate.getConnectionFactory();
        //3.通过redisTemplate获取连接
        JedisConnectionFactory factory2 = (JedisConnectionFactory) redisTemplate.getConnectionFactory();
        
        //指定使用redis中的哪个库(默认16个从0开始)
        factory2.setDatabase(1);
    }

redis 的 setnx() 与 getset()

  • setnx() 向redis中存储一个key-value,如果redis库中已存在,当前存储失败返回0,如果不存在,存储成功,返回1
  • get(key) 获取key的值,如果存在,则返回;如果不存在,则返回nil;
  • getset()命令:这个命令主要有两个参数 getset(key, newValue)。该方法是原子的,对key设置newValue这个值,并且返回key原来的旧值。
 	@Autowired
    public Jedis jedis;

    @Autowired
    public JedisPool jedisPool;

    @Test
    public void test() {
        //1.建立redis连接
        Jedis conn = jedisPool.getResource();

        long currentTime = System.currentTimeMillis();//当前时
        String lockTimeDuration = String.valueOf(currentTime);
        //将当前时间作为value 存储到redis中,存储成功返回1,否则返回0
        Long i = jedis.setnx("keys", lockTimeDuration);

    }

封装操作 redis 数据的工具类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.Set;
import java.util.concurrent.TimeUnit;
//封装向redis中存储获取数据的方法
//将工具类注入到容器中
@Component 
public class RedisUtils {
    //通过StringRedisTemplate对象操作redis,向redis中存储数据
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    //公用的存储方法,方法中判断数据类型,根据数据类型
    //向redis中存储,并设置有效时间
    public void set(String key, Object object, Long time) {
        // 存放String 类型
        if (object instanceof String) {
            setString(key, object);
        }
        // 存放 set类型
        if (object instanceof Set) {
            setSet(key, object);
        }
        // 设置redis中指定key的有效时间
        stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
    }
    //向redis中存储String类型数据
    public void setString(String key, Object object) {
        // 如果是String 类型
        String value = (String) object;
        stringRedisTemplate.opsForValue().set(key, value);
    }
    //向redis中存储set类型数据
    public void setSet(String key, Object object) {
        Set<String> value = (Set<String>) object;
        for (String oj : value) {
            stringRedisTemplate.opsForSet().add(key, oj);
        }
    }
    //通过key获取redis中String数据
    public String getString(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
    
    //设置redis中指定key的失效时间(毫秒)
    public boolean setTime(String key, Long time){
        if(null != key || time !=0){
           return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
        }else {
            return false;
        }
    }

}

二. java 操作 redis 各种类型数据示例

注意点: 此处使用 StringRedisTemplate 操作redis数据,存储与获取都是字符串类型,如果存储对象需要先将对象转换为JSON串,然后进行存储,如果存储与获取时不进行类型转换,例如对象就直接存储对象,获取时直接获取为该对象类型不进行转换则使用 RedisTemplate,该对象向redis中存储的是字节数组
通过命令操作

  1. 操作 String 类型,二进制安全的。意思是可以包含任何数据。比如jpg图片或者序列化的对象 ,最基本的数据类型,一个键最大能存储512MB。
	@Test
    public void test01() {

        //创建操作redis中String类型数据的对象 ValueOperations
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();

        //1.添加数据set()添加数据(如果添加这个数据在库中已经存在就变为了修改)
        valueOperations.set("username", "mingming");

        /*2.以层级关系目录形式添加数据*/
        valueOperations.set("user:01", "wwww");
        valueOperations.set("user:01", "cccc");

        //3.添加多条数据multiSet()
        //map中的key为redis的key,map中的值为redis的值
        Map<String,String> stringMap=new HashMap<>();
        stringMap.put("数据1","值1");
        stringMap.put("数据2","值2");
        stringMap.put("数据3","值3");

        valueOperations.multiSet(stringMap);

        //4.查询
        Object username=valueOperations.get("username");

        //5.查询多条,以集合中的数据为key进行查询
        List<String> keyStr=new ArrayList<>();
        keyStr.add("数据1");
        keyStr.add("数据2");
        keyStr.add("数据3");
        List<String> valL=valueOperations.multiGet(keyStr);

        //6.删除指定key数据
        stringRedisTemplate.delete("username");

        //6.模糊匹配
        Set<String> keys = stringRedisTemplate.keys("noteUserListenedPoi:" + "*");

        //7.批量删除
        stringRedisTemplate.delete(keys);

    }
  1. 操作 Hash 散列类型,是一个string类型的field和value的映射表,hash特别适合用于存储对象
	@Test
    public void test02(){
        //1.创建操作 Hash类型数据的对象
        HashOperations<String ,String,String> hashOperations = stringRedisTemplate.opsForHash();

        //2.添加数据,第一个为redis的key,第二个为当前数据的field,点三个为值
        hashOperations.put("userInfo","name","gggg");

        //3.添加多条 map类型
        Map<String ,String> map=new HashMap<>();
        map.put("age","18");
        map.put("sex","1");

        //userInfo为redis的key,map中的键为field,值为value
        hashOperations.putAll("userInfo", map);

        //4.根据key,与field查询redis中的Hash类型数据
        String name=hashOperations.get("userInfo","name");

        //5.查询多条,创建查询的field集合
        List<String> keyS=new ArrayList<>();
        keyS.add("age");
        keyS.add("sex");

        //查询多条返回List集合
        List<String> hashValL=hashOperations.multiGet("userInfo",keyS);
        //查询多条返回Map集合
        Map<String,String>hashValue= hashOperations.entries("userInfo");


       //6.删除
        hashOperations.delete("userInfo","name");
    }
  1. 操作 List 列表类型,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边)
	@Test
    public void test03(){
        //1.创建操作List类型数据的对象
        ListOperations<String ,String> listOperations= stringRedisTemplate.opsForList();

        //2.左上添加,第一个添加的会被后一个添加的挤压到下面
        listOperations.leftPush("student","liuliuliu");
        //3.右下追加,第一个添加的会被后一个添加的挤到上面
        listOperations.rightPush("students", "Zhao Liu");

        //4.查询,根据key与下标获取指定位置的数据,左闭右闭,两边包含,返回一个List
        List<String> students = listOperations.range("student", 0,2);

        //5.根据key与指定下标获取单个数据
        String stu = listOperations.index("student", 1);

        //6.获取当前List类型数据的长度
        Long total = listOperations.size("student");

        //7.删除List类型数据,key为student的,value值为"Li",在List中第二次出现的,
        listOperations.remove("student", 2, "Li");

        // 删除多条,有左删除一条,右删除一条等
        stringRedisTemplate.delete("student");
        //8.删除从左边开始删
        listOperations.leftPop("student");
        //9.删除从右边开始删
        listOperations.rightPop("student");
    }
  1. 操作 Set 无序集合类型,不允许重复的成员,是通过哈希表实现的,所有添加,删除,查找的复杂度都是O(1)
	@Test
    public void testSet() {
        //1.创建操作Set类型数据的对象
        SetOperations<String, String> setOperations = stringRedisTemplate.opsForSet();

        //模拟数据
        String[] letters = new String[]{"aaa", "bbb", "ccc", "ddd", "eee"};

        //1.批量添加
        setOperations.add("letters", letters);
        //2.批量获取
        Set<String> let = setOperations.members("letters");

        //3.删除redis中key为letters的set类型数据中的aaa,bbb数据*
        setOperations.remove("letters", "aaa", "bbb");
    }
  1. 操作 SortedSet 有序集合,不允许重复的成员,每个元素都会关联一个double类型的分数,通过分数来为集合中的成员进行从小到大的排序,zset的成员是唯一的,但分数(score)却可以重复
	@Test
    public void testSortedSet() {
        //1.创建操作sorted set数据的对象
        ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();

        //2.向redis中添加 sorted set 类型数据,需要将数据封装到 ZSetOperations 中
        //传递一个dubbo值指定该数据在sortedSet集合中的排序位置,
        ZSetOperations.TypedTuple<String> objectTypedTuple1 = new DefaultTypedTuple<String>("zhangsan", 99D);
        ZSetOperations.TypedTuple<String> objectTypedTuple2 = new DefaultTypedTuple<String>("lisi", 96D);
        ZSetOperations.TypedTuple<String> objectTypedTuple3 = new DefaultTypedTuple<String>("wangwu", 92D);
        ZSetOperations.TypedTuple<String> objectTypedTuple4 = new DefaultTypedTuple<String>("zhaoliu", 100D);
        ZSetOperations.TypedTuple<String> objectTypedTuple5 = new DefaultTypedTuple<String>("tianqi", 95D);

        Set<ZSetOperations.TypedTuple<String>> tuples = new HashSet<ZSetOperations.TypedTuple<String>>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        tuples.add(objectTypedTuple4);
        tuples.add(objectTypedTuple5);

        //添加数据
        zSetOperations.add("score", tuples);
        //获取多条数据,左闭右闭,返回Set集合
        Set<String> scores = zSetOperations.range("score", 0, 4);

        //获取长度
        Long total = zSetOperations.size("score");

        //删除redis的key为score,value值为 zhangsan和lisi的两个数据
        zSetOperations.remove("score", "zhangsan", "lisi");
    }
发布了48 篇原创文章 · 获赞 0 · 访问量 567

猜你喜欢

转载自blog.csdn.net/qq_29799655/article/details/105609129
今日推荐