初学者之Redis

文章目录

  • 前言
  • 一、什么是Redis
  • 二、Redis基本类型
  • 三、通用命令
  • 四、基础命令
    • 1.String类型
    • 2.List类型
    • 3.Set类型
    • 4.Hash类型
    • 5.Zset有序集合类型
  • 五、在Java中的运用
    • 1.配置信息
    • 2.配置类
    • 3.操作String类型
    • 4.操作Hash类型
    • 5.操作List类型
    • 6.操作Set类型
    • 7.操作ZSet类型
  • 六、修改营业状态的实例
  • 总结


前言

第一次学习Redis,最后的目标是在idea中连接redis。看了别人的文献,但是是有自己思路的,主要是用于自己的学习。更高级的应用在以后进行进阶。

一、什么是Redis

Redis是一个开源的、内存数据库,可以用作缓存、消息队列和流处理引擎。通常用来保存热点数据,提供高性能、低延迟的数据访问。它基于键值对的形式进行存储的。

  • 内存数据库:一种将数据主要存储在内存(RAM)而非磁盘(HDD\SDD)种的数据库系统,适合性能要求严苛的场景。
  • RAM:计算机的硬件,随机存取存储器。
  • 那为什么不只用Redis呢,还要用MySql?
    因为Redis是一个内存数据库,通过RAM进行存储的,主要存储在缓存中,极有可能丢失,所以它的持久性不是很好,所以要MySql+Redis共同使用。它有16个数据库。

二、Redis基本类型

  • 字符串:普通字符串。
  • 哈希:Java中的HashMap散列表。
  • 列表:Java中的LinkedList链表。
  • 集合:Java中的HashSet集合。
  • 有序集合:集合中每个元素关联一个分数,根据分数升序排列,且没有重复元素。

用一下别人的图:
初学者之Redis_第1张图片

三、通用命令

注意:命令不严格区分大小写

  1. 切换数据库,切换到第3个数据库:从0开始。
select 2
  1. 查看当前数据库key的数量,因为redis使用键值对的形式存储的。
dbsize
  1. 设置一个键值对。username : root。
set username root
  1. 获取所有的key。
keys *
  1. 清除当前数据库里面所有的键值对。
flushdb
  1. 清除所有数据库。
flushall

四、基础命令

  1. 检查key为username是否存在。
exists username
  1. 指定username移动到1号数据库。下标从0开始,1号对应下标为1的数据库。
move username 1
  1. 指定key为username在10秒后过期。
    expire英文意思:过期。
expire username 10
  1. 查看key为username还有多久过期。
ttl username
  1. 查看key为username是什么类型。
type username 

1.String类型

  1. 设置key为username的值为root。
set username root
  1. 获取key为username的值。
get username
  1. 在对应的key对应的值后面追加字符串。结果为:rootroot。
append username root
  1. 获取key对应的值的长度。
strlen username
  1. 设置key为username的值+1。
    incr --> increase增加。
incr username
  1. 设置key为username的值 - 1.
    decr -->decrease减少
decr username
  1. 加10。
incrby username 10
  1. 减10。
decrby username 10
  1. 截取下标为0~3之间的字符串,字符串具有下标,可索引。结果为:roo。
getrange username 0 2
  1. 从下标为1的key为username的值开始替换为xxx。结果为:rxxx。
setrange username 1 xxx
  1. 设置key为username的值为root并10秒后过期。
    实际上这一句可以拆分为set username root和expire username 10,但是有误差噢,取决于你输入这两行命令的时间误差。
setex username 10 root
  1. 如果存在username为root的就不会创建,如果没有,那就创建,就像mysql里面的create if not exists。
setnx username root
  1. 一次性设置多个值,Redis 默认将所有值存为字符串。
mset k1 v1 k2 v2 k3 v3
mset username root password root age 19
  1. 一次性获得多个值
mget username password age
  1. 同理如果全都不存在那么创建,不存在那就不创建。
msetnx username root password root
  1. 不存在那就当场set,如果存在,返回原来的值并设置新的指定值。
getset username 123456

2.List类型

  1. 将1个值或多个值插入到list的头部。头部最终结果是 3 2 1噢。
lpush list 1
lpush list 1 2 3
  1. 将1个值或者多个值插入到list的尾部。尾部最终结果是1 2 3噢。
rpush list 1
rpush list 1 2 3
  1. 通过区间获得具体的值。获取整个列表的值。
lrange list 0 -1
  1. 移除list的第一个元素。
lpop list
  1. 移除list的最后一个元素。
rpop list
  1. 通过下标具体获得某个值。下标从0开始。
lindex list 3
  1. 获得list长度。
llen list
  1. 移除list集合中指定个数的value,移除1个值为2的。
  • key:列表的名称(这里是 list)。
  • count:删除的数量和方向(这里是 1)。
  • 大于0 :从左边开始。>8从左边开始,删除最多count个的匹配项。
  • 等于0 :所有的匹配项。
  • 小于0 :从右边开始。<7从右边开始,删除最多count个匹配项。
  • value:要删除的值(这里是 2)。
  • lrem key count value
lrem list 1 2
  1. 截取list集合中下标为1到下标为3之间的元素集合,并覆盖原来的list集合。就相当于切片。
ltrim list 1 3
  1. 更新list集合当中下标为3的值变成123456,如果下标为3的值不存在则报错。
lset list 3 123456
  1. 将一个某一个具体的值插入到另一个具体元素的前面或者后面。
    before / after 基准元素 插入元素
    返回值为rootFront root rootAfter。
linsert list before root rootFront
linsert list after root rootAfter 

3.Set类型

  1. 往set集合中添加1个元素。
sadd set element
  1. 查看set集合中所有元素。
smembers set
  1. 查看set集合中是否存在元素。
sismember set element
  1. 随机抽取出1个元素。
srandmember set
  1. 随机抽取出2个元素。
srandmember set 2
  1. 随即删除set集合中某个元素。
spop set
  1. 移动set集合中的element元素到set2集合中。
smove set set2 element
  1. 作set2集合减去set集合的差集。
    set2 - set
sdiff set2 set
  1. set和set2的交集。
    set ^ set2
sinter set set2
  1. set和set2做并集并去重。
    set ^ set2 distinct
sinter set set2

4.Hash类型

  1. 往hash集合中存放键值对数据。
hset hash username root
  1. 从hash集合中获取数据。
hget hash username
  1. 同时往hash集合中添加多个值。
hmset hash username root password root
  1. 同时从hash集合中获得多个值。
hmget hash username password
  1. 获取hash集合中所有的键值对。
hgetall hash
  1. 删除hash集合中指定的key字段。
hdel hash username
  1. 获取hash集合的长度。
hlen hash
  1. 判断hash集合中指定字段是否存在。
hexists hash username
  1. 获取hash集合中所有的key。
hkeys hash
  1. 获取hash集合中所有的value。
hvals hash
  1. 指定hash集合中的指定增量。
    这里再hash表中的views字段增加1。
hincrby hash views 1
hincrby hash age 1 年龄增加1岁
  1. 如果不存在则直接设置值,存在则设置失败。
hsetnx hash password root

5.Zset有序集合类型

  1. 添加一个值。
    在zset里面添加一个score为1的first元素。
zadd zset 1 first
  1. 添加多个值。
zadd zset 2 cat 3 dog 4 bird
  1. 获取zset里面所有的元素。
zrange zset 0 -1
  1. 给zset集合中升序排序。-inf:负无穷。 +inf:正无穷。
    通过score排序。
zrangebyscore zset -inf +inf
  1. 升序排序并输出键值。
zrangebyscore zset -inf +inf withscores
  1. 指定socre范围排序。
    升序排序。
zrangebyscore zset 5 10 withscores
  1. 移除zset集合中指定的元素。
zrem zset cat
  1. 查看zset集合中元素个数。
zcard zset
  1. 反转指定范围。是指score从4到10范围之内的。
zrevrange azet 4 10

五、在Java中的运用

1.配置信息

并没有和druid是同样的缩进,在dev里面配置实际的信息。
初学者之Redis_第2张图片

2.配置类

关键问题1:什么是redis模板对象?
个人解析:redis模板对象是spring底层给我们封装好了redis的一系列命令操作,比如set、get,便于我们操作使用
关键问题2:什么是连接工厂对象?
个人解析:我们配置了redis连接信息后,在java中封装读取redis的连接信息,便于读取和连接。
关键问题3:什么是序列化器?
个人解析:序列化器负责将Java对象转换为字节数组(序列化)存储到redis中,以及字节数组转化为Java对象(反序列化),实现redis里面的数据与java对象的转换。如果没有,那么就会乱码。
代码如下:

@Slf4j
@Configuration
public class RedisConfiguration {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("开始创建redis模板对象...");
        RedisTemplate redisTemplate = new RedisTemplate();
        // 1.设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 2.设置redis key序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

3.操作String类型

测试类如下:

// 报错的记得加上这个
@SpringBootTest(classes = SkyApplication.class)
public class Test01 {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 操作字符串:redisTemplate.opsForValue()
     * 操作hash:redisTemplate.opsForHash()
     * 操作列表:redisTemplate.opsForList()
     * 操作集合:redisTemplate.opsForSet()
     * 操作有序集合:redisTemplate.opsForZSet()
     */
    @Test
    public void test01(){
        System.out.println( "开始测试:"+ redisTemplate);
        // 操作的是字符串类型
        redisTemplate.opsForValue().set("city","北京");
        String city = (String) redisTemplate.opsForValue().get("city");
        System.out.println(city);
        redisTemplate.opsForValue().set("code", "1234",3, TimeUnit.MINUTES);
        redisTemplate.opsForValue().setIfAbsent("lock", "1");
        redisTemplate.opsForValue().setIfAbsent("lock", "2");
    }
}

4.操作Hash类型

测试类如下:

/**
     * 操作hash
     */
    @Test
    public void test02(){
        HashOperations hashOperations = redisTemplate.opsForHash();
        // 1.创建redis键值对
        hashOperations.put("hashtable","username","root");
        hashOperations.put("hashtable","password","root");
        // 2.读取redis数据
        String username = (String) hashOperations.get("hashtable","username");
        String password = (String) hashOperations.get("hashtable","password");
        // 3.打印一下
        System.out.println(username);
        System.out.println(password);
        // 4.获得key
        Set keys = hashOperations.keys("hashtable");
        // 5.获得values
        List values = hashOperations.values("hashtable");
        System.out.println(keys);
        System.out.println(values);
        // 6.删除键值对
        hashOperations.delete("hashtable","password");
    }

5.操作List类型

测试代码:

 /**
     * 操作列表类型数据
     */
    @Test
    public void test03(){
        ListOperations listOperations = redisTemplate.opsForList();
        // 1.从头部插入
        listOperations.leftPushAll("listdemo","a","b","c");
        listOperations.leftPush("listdemo","d");
        // 2.从尾部插入
        listOperations.rightPushAll("listdemo","e","f");
        listOperations.rightPush("listdemo","g");
        // 3.获得整个list
        List mylist = listOperations.range("listdemo", 0, -1);
        System.out.println(mylist);
        // 4.从头部弹出
        listOperations.leftPop("listdemo");
        // 5.从尾部弹出
        listOperations.rightPop("listdemo");
        // 6.获得list容量
        Long size = listOperations.size("listdemo");
        System.out.println(size);

6.操作Set类型

测试代码:

/**
     * 操作Set集合
     */
    @Test
    public void test04(){
        SetOperations setOperations = redisTemplate.opsForSet();
        // 1.从集合中添加元素
        setOperations.add("setdemo","a","b","c");
        setOperations.add("setdemo","a","e","f");
        // 2.获得所有的元素
        Set set = setOperations.members("setdemo");
        // 3.获得集合的大小
        Long size = setOperations.size("setdemo");
        // 4.获得两个集合的交集
        Set intersect = setOperations.intersect("setdemo", "set2");
        System.out.println(intersect);
        // 5.获得两个集合的并集
        Set union = setOperations.union("setdemo", "set2");
        System.out.println(union);
        // 6.删除set里面的元素
        setOperations.remove("setdemo","a","b");
        // 7.获得差集
        Set difference = setOperations.difference("setdemo", "set2");
        System.out.println(difference);
    }

7.操作ZSet类型

代码如下:

/**
     * 操作Zset有序集合
     */
    @Test
    public void test05(){
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        // 1.添加元素
        zSetOperations.add("zsetdemo","a",10);
        zSetOperations.add("zsetdemo","b",20);
        zSetOperations.add("zsetdemo","c",30);
        // 2.通过score索引元素
        Set zset = zSetOperations.range("zsetdemo", 0, -1);
        System.out.println(zset);
        // 3.删除元素
        zSetOperations.remove("zsetdemo","a","b");
        // 4.增加元素的score
        zSetOperations.incrementScore("zsetdemo","a",10);
    }

六、修改营业状态的实例

在修改营业状态的时候,我们就不要用Mysql存储了,因为只有一个字段,如果我们为了一个营业状态创建一个表,显得杀鸡焉用牛刀,而且速度没有redis快,毕竟谁都想早点下班,所以我们用redis的内存存储快速存,快速取。由于没有涉及到数据模型Model层的运用就不用写service了。
代码示例:

@RestController("adminShopController")
@RequestMapping("/admin/shop")
@Slf4j
@Api(tags = "管理端营业信息接口")
public class ShopController {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 修改营业状态
     * 我们没必要存储在mysql里面 就为了一个status 就只有一个字段 显得杀鸡焉用牛刀
     * 我们通过redis的内存存储模式 快速存 快速取
     * @param status
     * @return
     */
    @PutMapping("{status}")
    @ApiOperation("修改管理端的营业信息接口")
    public Result setStatus(@PathVariable("status") Integer status) {
        log.info("修改管理端的营业接口,{}", status == 1 ? "营业中":"打烊中");
        redisTemplate.opsForValue().set("SHOP_STATUS", status);
        return Result.success();
    }

    @GetMapping("/status")
    @ApiOperation("查询管理端营业状态接口")
    public Result<Integer> getStatus(){
        Integer status = (Integer) redisTemplate.opsForValue().get("SHOP_STATUS");
        log.info("查询管理营业状态接口:{}", status == 1 ? "营业中":"打烊中");
        return Result.success(status);
    }
}

总结

redis是一个nosql类型的数据库,它通过键值对的形式进行存储,特别适合用于存取热点信息,消息队列等,它通过内存存储的形式在RAM中,更适合零散的场景,不适合二维表的形式的存储,可以理解为mysql是长刀,redis是短刀,都有自己的用武之地,二者结合,是最佳的实践。

你可能感兴趣的:(redis,数据库,缓存,java,后端,spring,spring,boot)