什么是redis ?

redis: 主要用来做数据缓存,redis运行在内存中,数据也保存在内存中。

缓存:让数据离程序更近。

一般也把redis称为中间件。数据库、缓存和消息中间件

NoSQL(Not Only SQL 不仅仅是 SQL):泛指非关系型的数据库。

关系型数据库与非关系型数据库

关系型数据库:使用标准的SQL语言进行操作(表与表之间的关系)

不能代替,基本的数据还是存储在关系型数据库中

优点:易于理解,使用方便,易于维护

sql不足:IO瓶颈,海量数据查询效率低。

非关系型数据库:没有固定的关系,以键值对的形式进行存储(key-value)

优点:结构简单易拓展(以键值对),高性能,灵活的数据类型。

不足:只适合存放简单的数据,不适合放时间太久,太多。

两者不是相互替代,是相辅相成的,相互协调。

Redis 优势

redis特点:

  • 易拓展

  • 高性能

  • 灵活的数据类型

Redis与其他非关系型数据:

  • 性能极高(读写速度快)

  • 丰富的数据类型(list、set、Map等)

  • 原子性 (所有的操作都是原子性的)

  • 丰富的特性 (支持publish,通知等)

Redis

  • 通过键值对存储在内存中,也可以存储在硬盘上。

  • 存储过程简单,高性能,易于扩展,支持多语言,保证操作的原子性。

  • 支持多种数据类型。

安装配置

  1. 安装准备

检查 gcc 版本: gcc -v

Redis6 以上版本要求 gcc 必须在 5.3 以上

如果不能满足需求,升级 gcc,步骤如下:

yum -y install centos-release-scl

yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

scl enable devtoolset-9 bash 需

要注意的是 scl 命令启用只是临时的,退出 shell 或重启就会恢复原系统 gcc 版本。 如果要长期使用 gcc 9.3 的话执行下面命令. echo -e "\nsource /opt/rh/devtoolset-9/enable" >>/etc/profile

如果已经安装 gcc,版本满足要求,跳过上面升级步骤. 如果没有安装 gcc,安装步骤:

dnf group install "Development Tools" dnf install man-page

  1. 安装
  2. 下载安装包
  3. 上传redis
  4. 解压: tar -zxvf redis-6.0.8.tar.gz
  5. cd redis-6.0.8
  6. 预编译:make
  7. 创建redis文件夹:mkdir -p /opt/redis
  8. 安装到指定的目录 : make install PREFIX=/opt/redis
  9. ./redis-server 启动服务

Redis的数据类型

redis是以键值对进行存储的,键都是String.

5种数据类型指的是数据类型:

String(字符串)、Hash、List、Set、Zset

6种底层数据结构: 简单动态字符串、双向链表、压缩列表、哈希表、调表和整数数组

存储数据的时候,用的是Hash结构,可以通过key来计算位置,将key-value都存储在此位置。

哈希冲突问题:

它提供两块内存空间,相当于扩容,将原来的映射,渐进式的复制到扩容后的哈希表中,然后释放之间的空间。

String(字符串)

单值缓存

例:

  • set  key value
  • get ket
  • del key

对象缓存

建议对象的值,不再改变。

例:set user:1 value(json 格式数据)  如:品牌规格等

计数器 

例:

  • set   news_views:1   0   设置文章的访问量
  • incr   news_views:1   +1  值自增 1,值必须是数字。
  • decr    news_views:1   -1  值自减1,
  • get     news_views:1   获得值

Web集群 session 共享

   session + redis 实现session共享

Hash结构

适合存储数据(适合存储需要改变对象属性值的场景)

users: acc1  123   ph1   153

             acc2   312  ph2  135

  • hset   key   属性  值   存储一个哈希表key的键值。
  • hmset key  属性1   值1  属性2   值2
  • hmget  key 属性1 属性2
  • hdel   key  属性    获取哈希表key对应的属性键值
  • hlen  key 返回哈希表key中的属性的数量
  • hgetall  key  返回哈希表key 中所用的键值
  • hincrby   key   属性   增加的值(减少给负数)

List(列表)

  • lpush   key  value[value...]   将一个或多个值插入到key列表的表头
  • rpush   key  value[value...]   将一个或多个值插入到key列表的表尾
  • lpop  key  移除并返回key列表的头元素
  • rpop  key  移除并返回key列表的尾元素
  • lrange  key start stop 返回列表key中指定区间内的元素,区间以偏移量start 和 stop

Set(集合)

Redis的Set集合是无序集合。

  • sadd key member[member...] 往集合 key 中存入元素,元素存在则忽略,若 key 不存在则新建
  • srem key member[member...] 从集合 key 中删除元素
  • smembers key 获取集合 key 中所有元素
  • scard key 获取集合 key 的元素个数

Zset(有序集合)

redis zset 也是不允许重复的成员,但是是有序的。

Redis相关问题

redis线程模型

redis是单线程模式还是多线程模式.

不同版本的区别:

6.x之前是真正意义上的单线程,处理客户端的连接和执行操作的命令,都是由一个线程完成的。

6.x之后引入多线程,处理客户端请求是由专门的线程处理,执行命令还是单线程。

为什么是单线程模式,速度还非常快?

  1. 数据存储在内存中,读取速度快,cpu不是性能瓶颈

  2. 结构简单,key-value 底层是哈希结构,查询操作速度是O(1)

  3. 采用IO多路复用,非阻塞IO模型,提高连接访问效率

  4. 单线程执行命令,不存在线程切换,节省开销,而且是线程安全的。

Redis 持久化

IO对象序列化,对象的反序列化 对象信息持久保存到硬盘上。

mysql jdbc

mybatis 是一个java的数据持久层框架

redis数据是存储在内存中,内存数据是临时保存的。

redis是支持将数据持久化到硬盘。

redis是如何进行数据持久化的? 

RDB(Redis DataBase)和AOF(Appebd Only File)

这两种方式都在redis.conf文件可以配置

redis默认使用RDB方式。

配置触发持久化的机制:

  1. save m n save 多少秒内 多少键

  2. flushall 命令

  3. 退出

AOF:

以日志的形式,将写命令存储到文件 set name jim

还原时,将命令逐个执行还原数据

默认是不开启的 appendonly no

同步机制

appendfsync always 每次set记录一次

appendfsyns everysec 每秒记录一次

Redis事务

redis在执行单条命令时,是原子性(单线程的一次只能有一个线程执行命令),有时候,一次操作需要执行多条命令,如何保证多条命令整体执行。

可以通过redis事务执行:

开启事务:multi

添加命令:... 命令添加进来不会立即执行,添加到一个多列。

执行exec命令时,才会将对列中的多条命令依次执行,执行一个事务多条命令时,其他客户端会被隔离,不会交替执行,但是事务不保证多条命令执行的原子性(假如执行3条命令,其中一条语法错误,那么会将其他两条正确的命令继续执行)

  • 开始事务(MULTI)
  • 命令入队
  • 执行事务(EXEC)、撤销事务(DISCARD )

主从复制

主从---> 主机和从机(集群架构)

主机负责写数据,将数据同步到从机,一般的读数据从从机查询,

实现读写分离:写命令由主机执行,而读命令由从机执行

为什么要使用集群?

如果只有一台redis服务,万一服务宕机,所有的请求都会到达mysql,导致mysql宕机,可以搭建多台redis服务器,如果其中一台出现故障,其他服务可以正常使用。

哨兵机制

有一个单独线程,对集群中的多态服务进行监听,给每个服务发请求,如果没有响应,表明出现故障。

比如,主机出现宕机,会在从机随机选取一台当做主机。

当原来主机恢复后,又可以当做主机继续使用。

key的过期策略

为key设置过期时间,那么时间到了后,Redis如何处理过期的key

  1. 立即删除。到期立即执行回调函数,立即释放内存,对redis性能有影响。

  2. 惰性删除。到期不会立即删除,到下次使用该键的时候,根据状态(设置时是会记录的),来决定是删除还是继续使用,占用内存)

  3. 定期删除。每隔一段时间对所有到期的键进行删除(类似于java中垃圾回收线程)

缓存穿透

我们所查询的数据在数据库中没有,查询后也不在缓存中存,每次还是回去访问数据库。

特点:数据库没有,缓存也没有

解决:

  • 本来数据库没有,将查询出来的空值放到缓存中。key = null

  • 对查询的参数进行验证

缓存击穿

数据库有数据,只是某个热点key在某个时间点上过期了,此时有大量查询请求到达(查询是不加锁),查询缓存没有,一起都向数据库发送请求,导致数据库崩溃。

解决:

  • 可以设置热点的key过期时间要把握好(永不过期

  • 查询缓存后,访问数据库时,可以加锁(使用互斥锁方案

缓存雪崩

大量的热点key过期或者redis服务器故障,导致大量的请求到达数据库。

解决方案:

  • 随机设置有效时间,避免同时生效

  • 把不同的热点key放在不同的redis服务器上(集群)

  • 设置较长的过期时间

  • 在java中设置定时任务,去检测key是否过期

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐