Redis基础学习笔记

Redis简介

本文链接https://blog.csdn.net/Lxjlxj233/article/details/106797968
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

Redis 优势

  • 性能极高 – Redis读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Redis的key-value存储优点

  • Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
  • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存。在内存数据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Redis 数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String(字符串)

  • string是redis最基本的类型,一个key对应一个value。
  • string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
  • string类型是Redis最基本的数据类型,一个键最大能存储512MB。
  • redis为字符分配空间的次数是小于等于字符串的长度N,而原C语言中的分配原则必为N。降低了分配次数提高了追加速度,代价就是多占用一些内存空间,且这些空间不会自动释放。
  • 高效的计算字符串长度(时间复杂度为O(1))。
  • 高效的追加字符串操作。

实战场景:

  • 缓存、计数器、分布式锁
  • 记录网站每个用户个人主页的访问量(单线程:无竞争。不会出错 incr key)
  • 缓存视频的基本信息(数据源在Mysql中)
  • 分布式id生成器:三个应用,我们希望三个应用每次获取的Id自增 (incr key)

本人工作中用到过的案例:

  • 记录游戏中玩家抽奖总次数(incr key)

  • 抽奖贵重奖品数量校验分发(setnx)

    //获得锁
    public boolean getLock(String locked,long time){
    //当键不存在的时候,设置键的值,并且该方法可以设置键的过期时间。
    Boolean flag = redisTemplate.opsForValue.setIfAbsent(locked,"lock",time,TimeUnit.MILLISECONDS);
    	return flag != null && flag;
    }
    //释放锁
    public void releaseLock(String locked){
        reisTemplate.delete(locked);
    }//在释放锁的时候,是存在释放失败的风险的,这也是为什么在设置锁的时候需要设置过期时间的原因,可以防止在出现异常的时候,锁会自动的消失掉。也可以增加几次失败之后的重试机制。
    

基础命令:

  • 存:set key value
  • 取:get key
  • 删:del key

Hash(哈希)

  • Redis hash 是一个键值对集合。
  • Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

实战场景:

  • 一般可以用来存某个对象的基本属性信息,例如,用户信息,商品信息等,ziplist结构,比较节约内存
  • 记录网站每个用户个人主页的访问量
  • 缓存视频的基本信息(数据源在Mysql中)

基础命令:

  • 存:hset key field value
  • 取:hget key field hgetall key
  • 删:hdel key field

List(列表)

  • Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际上是个链表。

实战场景:

  • 消息队列,分页查询。
  • 微博时间轴功能,微博从新到旧的顺序排列。每一个微博是一个对象,例如hash或字符串。然后你的微博Id作为key,你可以lrange获取0~10条微博然后mset获取所有内容,再序列化做出接口。

基础命令:

  • 添加:lpush key value / rpush key value
  • 范围获取:lrange key start end
  • 删除元素并将其返回:lpop key rpop key

Set(集合)

  • Redis的Set是string类型的无序集合,且不允许重复的成员,可以想到数学里集合的概念。交集、并集和差集。
  • 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

实战场景:

  • 去重功能,对集合进行交集,并集操作,来查找某些元素的共同点。
  • 微博转发抽奖平台(spop key:从集合随机弹出一个元素)。
  • 点赞、踩。
  • 共同关注。
  • 给用户添加标签(sadd key element)向集合Key添加element,若存在则失败。

基础命令:

  • 存储: sadd key value
  • 获取集合所有元素:smembers key
  • 删除集合某个元素:srem key value

Zset(有序集合)

  • sorted set:有序集合。
  • Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
  • 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
  • zset的成员是唯一的,但分数(score)却可以重复。

实战场景:

  • 范围查找
  • 排行榜:分数添加更新
  • topN功能

基础命令:

  • 存储:zadd key score value
  • 获取:zrange key start end
  • 删除:zrem key value

redis持久化

由于redis是一个内存数据库,当redis服务器重启或者redis挂掉,数据会丢失,所以需要持久化到硬盘。

RDB

RDB(Redis DataBase)是将某一个时刻的内存快照(Snapshot),以二进制的方式写入磁盘的过程。

RDB持久化触发方式
  • 手动
    • save(阻塞):会阻塞redis主进程,直到 RDB 持久化完成,redis才会响应其他客户端发来的命令。
    • bgsave(非阻塞):bgsave(background save)既后台保存,它和save的巨大区别是它会fork()一个子进程来执行持久化,整个过程中只有fork()子进程时有短暂的阻塞。
  • 自动
    • save m n:在m秒内如果有n个键发生改变,则会自动触发持久化。
      • 本质是redis通过根据持久化的触发条件判断,自动执行bgsave。
      • 当设置多个 save m n 命令时,则满足其中一个条件就会自动触发持久化。
RDB文件恢复

当 Redis 服务器启动时,如果 Redis 根目录存在 RDB 文件 dump.rdb,Redis 就会自动加载 RDB 文件恢复持久化数据。

验证 RDB 文件是否被加载:Redis 在启动时有日志信息(redis.conf),会显示是否加载了 RDB 文件。

RDB优点
  • RDB数据为二进制,数据占用内存小,紧凑。
  • RDB对灾难恢复非常有用,它是一个紧凑的文件,可以更快得传输到远程服务器进行Redis服务数据恢复。
  • RDB对Redis的运行速度影响很小,因为每次持久化之前主进程会fork()一个子进程,进行数据持久化到硬盘,主进程不会进行I/O操作。
  • RDB持久化,重启redis比较快。
RDB缺点
  • 因为RDB是在单位时间内指定个key发生变化后执行的持久化,所以会导致最后一次持久化后的数据丢失。
  • RDB需要经常fork()子进程,这一过程是会阻塞主进程的,如果数据集过大或者CPU性能不佳就会导致Redis在fork()子进程的时间赢。

AOF

Append Only File,将除了读之外的所有指令以文本的形式追加到AOF文件中,不允许除添加之外的任何操作。

AOF持久化触发方式

修改redis的配置文件,把appendonly选项改为yes,redis即开启了AOF数据持久化模式。

设置AOF同步的方式,这里设置的默认的每秒同步一次,修改配置文件,appendsync。

  • always:
    • 表示缓冲区的数据发生更改,则就将该数据写入AOF文件中。
    • Redis 在每个事件循环都要将 AOF 缓冲区中的所有内容写入到 AOF 文件,并且同步 AOF 文件,所以 always 的效率是 appendfsync 选项三个值当中最差的一个,但从安全性来说,也是最安全的。当发生故障停机时,AOF 持久化也只会丢失一个事件循环中所产生的命令数据。
  • everysec(默认的方式):
    • 每秒都把缓冲区的数据写入到AOF中。
    • Redis 在每个事件循环都要将 AOF 缓冲区中的所有内容写入到 AOF 文件中,并且每隔一秒就要在子线程中对 AOF 文件进行一次同步。从效率上看,该模式足够快。当发生故障停机时,只会丢失一秒钟的命令数据。
  • no:
    • 不做任何策略配置,将策略配置交给操作系统,一般操作系统是在缓冲区被占完后将数据写入AOF文件中
    • Redis 在每一个事件循环都要将 AOF 缓冲区中的所有内容写入到 AOF 文件。而 AOF 文件的同步由操作系统控制。这种模式下速度最快,但是同步的时间间隔较长,出现故障时可能会丢失较多数据。
AOF文件恢复
  • AOF 文件里边包含了重建 Redis 数据所需的所有写命令,所以 Redis 只要读入并重新执行一遍 AOF 文件里边保存的写命令,就可以还原 Redis 关闭之前的状态。
AOF优点
  • 数据非常完整,故障恢复丢失数据少
  • 保存的命令,可读性高
AOF缺点
  • 文件体积较大(保存除读之外的所有命令)
  • 数据恢复时间长(需要执行所有写命令)
AOF重写策略

AOF重写策略解决了AOF文件不断增加的问题。

CopyOnWrite:写时复制,当父线程与子线程同时对一个共享数据进行操作时,如果数据没有发生改变,那么父子线程仅仅是进行读操作,那么共享数据不会发生改变;但是如果某个线程进行了写操作,共享数据发生了改变,那么将生成一个数据的复本供父线程使用。

AOF重写过程:

  1. redis服务fork一个子进程,该子进程不依赖已存在的AOF文件,仅通过redis已有数据生成新的AOF文件。
  2. 主进程实时的将redis中的数据变动写入AOF缓冲区和重写缓冲区。
  3. 子进程通知主进程完成对旧数据的AOF重写。
  4. 主进程将重写缓冲文件添加到子进程完成重写之后的AOF文件后,形成新的AOF文件替换老的AOF文件。

Redis架构

单机

https://www.jianshu.com/p/df66a882c899

主从复制(Master&Slave)

https://www.cnblogs.com/wade-luffy/p/9639986.html#_label1_0

主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。

作用:

  1. 负载均衡(读写分离)
  2. 数据热备份(持久化之外的另一种备份方式)
  3. 容灾恢复(当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复)
  4. 高可用的基础(哨兵和集群能够实施的基础)

配置:

配置从库不配主库:主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。

从节点开启主从复制:

  • 配置文件:在从服务器的配置文件中加入:slaveof
  • 启动命令:redis-server启动命令后加入 --slaveof
  • 客户端命令:Redis服务器启动后,直接通过客户端执行命令:slaveof ,则该Redis实例成为从节点。

断开主从复制:通过slaveof 命令建立主从复制关系以后,可以通过slaveof no one断开。从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。

哨兵

https://www.jianshu.com/p/06ab9daf921d

集群

https://blog.csdn.net/miss1181248983/article/details/90056960

(待完善)…

你可能感兴趣的:(redis,redis)