初步了解Redis

1. redis

简而言之,redis就是以key-value形式存储数据的非关系型数据库

redis的定位是缓存,提高数据读写速度,减轻对数据库的存储与访问压力

1.1 redis的优缺点

redis具有以下优点:

  • 性能极高:对数据进行高并发读写–>因为他是直接在内存中进行读写的
  • 对海量数据的高效率存储和访问
  • 对数据的可拓展性和高可用性
  • 因为是单线程操作,所以天生就是性能安全的

redis具有以下缺点:

  • 不支持事务
  • 无法处理复杂的关系数据库模型

1.2 redis中的数据类型

redis 中所有命令操作都大致如下 :

​ 类型命令 key 参数数据

1.2.1 String类型

Map<String,String> map

  • set key value : 存入键值对
  • get key : 根据键,取值
  • incr key : 根据键,将该键的值增加 1
  • decr key : 根据键,将该键的值减少 1
  • setex key timeout value : 存入一个键值对, timeout 表示这个键值对多久后过期,单位秒
  • ttl key : 查询指定key还有多久时间过期,返回值为 -1 时说明是永久的, -2 说明不存在或已经销毁
  • setnx key value : key不存在时存入该键值对,key存在时不做反应
  • mset key1 value1 key2 value2 : 批量存入键值对

存入键值对时,如果key值相同时,后者覆盖前者

可以用于计数器等场景

1.2.2 hash类型

hash类型结构大致如下 :

Map< String , Map<String,String> > map
在这里插入图片描述

  • hset key hashkey hashvalue : 存入一个hash对象
  • hget key hashkey : 根据hash对象的hashkey值,取其对应的hashvalue值
  • hexists key hashkey : 判断hash对象是否拥有某个键
  • hdel key hashkey : 根据hash对象的hashkey,删除对应的键值对
  • hlen key : 获取hash对象键的数量
  • hkeys key : 获取hash对象的所有键
  • hvals key : 获取hash对象的所有值
  • hgetall key : 获取hash对象的所有数据
    在这里插入图片描述

在实际开发中, hash 类型用的很少,一般不建议使用

1.2.3 list类型

list类型是类似于双向链表的结构,既可以作为栈,又可以作为队列

Map <String,List> map

  • rpush key value : 在右边添加键值对
  • lpush key value : 在左边添加键值对
  • lpop: 弹出最左边的数据
  • rpop: 弹出最右边的数据
  • lrange key start end : 范围显示列表数据,想全部显示则将范围设为: 0 -1
  • llen key : 获取列表长度
  • lset key index value : 根据索引修改数据 , 索引是从0开始的
  • lindex key index : 根据索引取列表中数据
    在这里插入图片描述

可以用于一个用户收藏了什么文章的类似场景

1.2.4 set类型

String类型的 , 无序的 集合

  • sadd key value : 向集合中添加元素
  • smembers key : 列出指定集合的数据
  • srem key value : 删除集合中的元素
  • spop key count : 随机弹出指定数量的集合中的元素
  • sdiff key1 key2 : 返回key1集合的差集
  • sinter key1 key2 : 返回两集合交集
  • sunion key1 key2 : 返回两集合并集
  • scard key : 返回指定集合元素个数
    在这里插入图片描述

适用于去重 , 或者抽奖之类的应用场景

1.2.5 zset类型

  • zadd key num name : 向指定集合中存入分数和名称
  • zrange key start end : 从start到end,按照分数升序输出名称
  • zrevrange key start end : 从start到end,按照分数降序输出名称
  • zrank key name : 按照升序,返回指定集合中,name的排名
  • zrevrank key name : 按照降序,返回指定集合中,name的排名
  • zcard key : 返回指定集合中的元素个数

zset可以用来做 实时排行
在这里插入图片描述

总结 :

  • 需要排序 : zset
  • 数据是多个,允许重复:list
  • 数据是多个,不允许重复:set
  • 其他 :string

设计key和value的原则:保证 :唯一性,可读性,灵活性,时效性

1.3 redis进阶

1.3.1 高级命令

  • keys * : 返回所有键 , 可以拓展使用 , 比如 : keys ha* 就是返回以 ha 开头的所有 key
  • exists key : 查询是否存在指定 key , 存在返回 1 , 不存在返回 0
  • expire key seconds : 为一个 key 设置过期时间,时间一到该 key 就会销毁
  • persist key : 取消指定 key 的过期操作
  • flushdb : 清空当前数据库
  • flushall : 清空所有数据库
  • select [数字0~15] : 选择进入某个数据库,一共有16个,默认在第0个数据库
  • dbsize : 查看数据库中 key 的数量

1.3.2 redis的持久化机制

redis缓存是暂时将数据保存在内存中的,但是有时候数据会需要持久化,这需要将内存中的数据同步到硬盘来保证数据的持久化,而 Redis 进行持久化有两种方式:

  • RDB方式 :

    可以通过配置,使 redis 在n秒内,如果超过指定数量的key被修改了,就自动同步

    但是这种方式存在缺点,因为有时间间隔,如果在间隔内出现意外,数据就会丢失

  • AOF方式 :

    append-only file 的缩写

    使用这种方式,redis会将所有收到的命令,用类似于MySQL中的SQL语句一样的形式,写在文件中,当redis再启动时,再读取这些命令,将数据写回内存中

    启动 aop 持久化有三种方式:

    • always :收到命令就立刻写到磁盘
    • everysecond :每秒写入一次(折中方式,建议)
    • no :完全依赖os

1.4 redis的实际运用

1.4.1 jedis的使用

使用jedis之前先导入相关依赖:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

注意在 redis 中的命令,就是 jedis 中的方法,两者长得一模一样

@Test
public void testJedis(){
    // 1:创建Jedis连接池,告诉端口在哪
    JedisPool pool = new JedisPool("localhost", 6379);
    // 2:从连接池中获取Jedis对象
    Jedis jedis = pool.getResource();
    // 3:我们只需要操作这里就行
    

    // 4:关闭资源
    jedis.close();
    pool.destroy();
}

其中,1,2,4 步是固定的,只需要去操作第三步就行,比如:

//存入一个键值对
jedis.set("no1", "66");
//删除一个键值对
jedis.del("no1");
....

1.4.2 SpringBootTemplate 使用

继承SpringBoot,以SpringBootTemplate 的方式使用

导入相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

修改配置文件:

#application.properties
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=admin #根据情况配置

使用 SpringBootTemplate 操作 redis , 相关的类是:RedisTemplate<Object,Object> template

但是因为一些公司规定,key-value都使用string类型,所以 上面那个类等价于:StringRedisTemplate

在调用的方法上来说,一般用 StringRedisTemplate 调用的方法和jedis有所区别,很多都是名称补全的

调用不同类型的方法的对象如下:

template.opsForValue().xxx(); 	//操作字符串
template.opsForHash().xxx(); 	//操作hash类型
template.opsForList().xxx();	//操作list类型
template.opsForSet().xxx();	 	//操作set类型
template.opsForZSet().xxx(); 	//操作Zset类型

对于一些 redis 的全局命令而言,直接就是 template 的方法

//删除所有键值对
Set<String> keys = template.keys("*");
template.delete(keys);
//查询 xx 过期时间
template.getExpire("xx");
//是否存在某个键
template.hasKey("xx");
//取消某个键过期时间
template.persist("xx");

1.5 其他

项目中操作涉及到缓存操作,首选redis,但是不是唯一可选的,还有 memcache

有些公司会约定:所有的redis的key跟value都使用字符串(排除使用zeset场景)

redis事务的执行不是原子性的(所以其实就是不支持事务,没意思~)

默认缓存大小为100M,所以当缓存在快要达到100m时,就会触发redis的内存淘汰机制

实战小项目:

​ 需求 :模拟显示一篇文章的访问量 :

思路:

  • 每次访问,访问数加1并显示在页面上
  • 每次访问页面,立刻 发送异步请求到控制层,带上当前文章的 id
  • 控制层接受到文章 id , 调用业务层方法,将对应文章的访问数加1,并将访问数返回给前端页面的回调函数
  • 在回调函数中,把参数设置给页面的访问数量

业务层:

@Autowired
private StringRedisTemplate template;

// 拿到 id 之后,给对应id的文章的阅读数量,加一,然后将阅读数返回
@Override
public int CountRead(String id) {

    //因为我们的key设计,需要考虑到可读性,此处一个id,让人摸不着头脑
    //增强其可读性,做到见名知义
    String key = "articleId:" + id;

    // 找到数据库中 key 对应的value,将其递增1,返回value值,是Long类型
    Long totalRead = template.opsForValue().increment(key);
    // Long类型转化为 int 类型并返回
    return totalRead.intValue();
}

控制层:

@RestController
@RequestMapping("read")
public class ReadController {
    @Autowired
    private IReadService readService;
    @PostMapping("/countAdd")
    public Object countAdd(String id){
        //在这里调用业务方法,完成阅读数+1
        //拿到返回的阅读数,返回给前端
        int totalRead = readService.CountRead(id);
        return totalRead;
    }
}

前端页面:

<script>
    // 页面加载完毕执行
    $(function () {
        // 发送异步请求,参数为文章的 id , 模拟写一个假id上来
        $.post("/read/countAdd",{id:666},function (data) {
            // 回调函数data就是文章的阅读数,就是存在 redis 中的key-value的value值
            // 将这个value值赋值给对应标签
            $("#totalRead").html(data);
        })
    }</script>

2 MongoDB和Redis的区别

Redis 缓存 : 数据存在内存中,其“缓存”的性质,远远大于其“数据存储”的性质,其数据的增删改查也只是像变量操作一样简单

MongoDB 数据库 :存储数据的系统,增删改查可以添加很多条件,就像SQL数据库一样很灵活

两者都是非关系型数据库–NoSQL,采用结构型数据存储,主要区别在于:

  • 内存管理:

    • Redis数据全部写在内存中,定期写入磁盘,内存不够时,采用LRU算法删除数据
    • MongoDB的数据会优先存在内存中,内存不够时,只将热点数据放入内存,其他数据存在磁盘
  • 数据结构:

    • Redis支持丰富的数据结构:包括hash,set,list
    • MongoDB数据结构比较单一,但是支持丰富的数据表达,索引,最类似关系型数据库
  • 数据量和性能:

    • 当物理内存够用的时候,性能:redis>MongoDB>mysql

      数据量:mysql>mongodb>redis

  • 可靠性:

    • MongoDB 采用binlog的方式,支持持久化,增加可靠性
    • redis 依赖快照进行持久化,AOF增强可靠性,但是同时会影响到访问性能

    因此MongoDB的可靠性优于redis

两者各自的应用场景:

在说应用场景之前先说一个概念 :

TPS : Transactions Per Second : 每秒传输的事务处理个数 ,即服务器每秒处理的事务数;TPS 包括一条消息入和一条消息出,加上一次用户数据库访问

场景一:项目要求 TPS 特别高的,比如微博点赞数,触发频率很高,并发量很大 : 使用 redis

场景二:项目中设计评论的内容,且这个评论表的数据后期会很大,而且还会要求在这个庞大数据量的情况下进行复杂的查询:使用 MongoDB

场景三:推送,评论,用MongoDB,目前是百万级数据,以后是千万级,亿级

ongoDB 采用binlog的方式,支持持久化,增加可靠性

  • redis 依赖快照进行持久化,AOF增强可靠性,但是同时会影响到访问性能

因此MongoDB的可靠性优于redis

两者各自的应用场景:

在说应用场景之前先说一个概念 :

TPS : Transactions Per Second : 每秒传输的事务处理个数 ,即服务器每秒处理的事务数;TPS 包括一条消息入和一条消息出,加上一次用户数据库访问

场景一:项目要求 TPS 特别高的,比如微博点赞数,触发频率很高,并发量很大 : 使用 redis

场景二:项目中设计评论的内容,且这个评论表的数据后期会很大,而且还会要求在这个庞大数据量的情况下进行复杂的查询:使用 MongoDB

场景三:推送,评论,用MongoDB,目前是百万级数据,以后是千万级,亿级

场景四:直播弹幕等用redis,用来存储一些热数据,量不大但是操作频繁

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值