Redis

概述:

        Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的,使用C语言编写的,支持网络交互的,内存中的Key-Value数据结构存储系统,支持多种语言,它可以用作数据库、缓存和消息中间件。

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

        1.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

        2.Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

        3.Redis支持数据的备份,即master-slave(主-从)模式的数据备份。

Redis 优势

        1.性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。

        2.丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。

        3.原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。

        4.丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

为什么使用Redis?

关系型数据库

        采用关系模型来组织数据的数据库,关系模型就是二维表格模型。一张二维表的表名就是关

系,二维表中的一行就是一条记录,二维表中的一列就是一个字段。
        优点:

                1.容易理解

                2.使用方便,通用的sql语言

                3.易于维护,丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大降低了数据冗余和数据不一致的概率缺点

        缺点:

                1.磁盘I/O是并发的瓶颈

                2.海量数据查询效率低

                3.横向扩展困难,无法简单的通过添加硬件和服务节点来扩展性能和负载能力,当需要对数据库进行升级和扩展时,需要停机维护和数据迁移。

                4.多表的关联查询以及复杂的数据分析类型的复杂sql查询,性能欠佳。因为要保证ACID。

非关系型数据库

        非关系型,分布式,一般不保证遵循ACID原则的数据存储系统。键值对存储,结构不固定。

优点

          结构简单易扩展

          高性能

        灵活的数据模型

缺点

        只适合存储一些较为简单的数据

        不适合复杂查询的数据

        不适合持久存储海量数据

Linux下安装Redis:

        1.下载:https://redis.io/download

                wget  https://download.redis.io/releases/redis-6.2.4.tar.gz

                或者 上传

        2.解压:tar -zxvf  redis-6.0.8.tar.gz

        3.make:本地编译源码

        4.mkdir -p /opt/redis:创建文件

        5.make install PREFIX=/opt/redis:安装到指定目录

        6.cd /opt/redis/bin:进入安装文件bin目录

        7.        ./redis-server 启动服务

redis基本设置:

       1. 从redis的源码目录中复制 redis.conf 到 redis 的安装目录,

        进入到redis源码包 redis-6.0.8   里面有个redis.conf的配置文件         

        cp redis.conf  /opt/redis/bin/

        2.文件内搜索  :vim redis.conf 

                在命令模式下 /搜索的内容 回车

        3.设置redis服务启动后,处于后台运行,这样就不影响我们正常的其他操作。

                 daemonize no  改为 daemonize  yes.

        4.设置远程访问,注释 绑定的id,默认只能本机访问,这样就可可以远程访问了。

                
        5.为redis设置连接密码  

                requirepass  你的密码

                启动命令:./redis-server redis.conf

                查看Redis运行状态:ps -ef | grep redis

                进入客户端模式:./redis-cli

                输入密码:auth 密码

                测试:ping

                ctrl+c退出客户端模式

Redis数据类型:

5种基本常用类型:

        string(字符串)  hash(哈希) list(列表)set(集合 ) zset(sorted set:有序集合)

 String(字符串):

        string 是 redis 最基本的类型,一个 key 对应一个 value。

        string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。

        string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

单值缓存

        set key value

        get key

        del key

        keys *

对象缓存(不对对象中数据操作时可以使用)

   set user:1 value(json格式数据)

计数器

           set    news_views:1  0  设置文章访问量

           incr   news_views:1     文章访问量+1

           decr  news_views:1      文章访问量-1

           get   news_views:1      获得值

Web集群session共享

    session + redis 实现session共享

Hash(哈希)

        redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象(对对

象中的数据发生修改情况)。

        存的是字符串和字符串值之间的映射,比如要存储用户购物车等信息。

        hset  key field value 存储一个哈希表key的键值

        hmset key field value [field value …]  存储多个键值对

        hget key field 获取哈希表key对应的field键值

        hmget key field [field …] 批量获取哈希表key中多个field键值

        hdel key field [field …]  删除哈希表key中的field键值

        hlen key 返回哈希表key中的field的数量

        hgetall key 返回哈希表key中所有的键值

        hincrby key field 增加的值(减少给负数)

List(列表)

        Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左

边)或者尾部(右边)。 

        

        lpush  key  value[value...] 将一个或多个值插入到key列表的表头(最左边)

        rpush  key  value[value...] 将一个或多个值插入到key列表的表尾(最右边)

        lpop   key   移除并返回key列表的头元素

        rpop   key   移除并返回key列表的尾元素

        lrange  key start stop 返回列表key中指定区间内的元素,区间以偏移量start和stop

 常见用法

        Stack= LPUSH + LPOP =FILO

        Queue= LPUSH + RPOP

 使用场景:可以用来存储接收到的消息数据。

Set(集合)

        Redis 的 Set 是无序不重复集合。

        sadd  key member[member...]   往集合key中存入元素,元素存在则忽略,key不存在则新建

        srem  key member[member...]  从集合key中删除元素

        smembers   key   获取集合key中所有元素

        scard   key        获取集合key的元素个数

Zset(sorted set:有序集合)

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

        不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进

行从小到大的排序。

        zset的成员是唯一的,但分数(score)却可以重复。

        zadd key score member[[score member]..] 往有序集合key中加入带分值元素

        zrem   key member[member...]    从有序集合key中删除元素

        zscore  key member    返回有序集合key中元素member的分值

        zincrby  key increment member  为有序集合key中元素member的分值加上increment

        zcard key    返回有序集合key中元素个数

        zrange key start stop[withscores]  正序获取有序集合keyastart下标到stop下标的元素

        使用场景:记录微信朋友圈记录点赞用户

 设置失效时间

        有时候我们并不希望redis的key一直存在。例如缓存,验证码等数据,我们希望它们能在一定时间内自动的被销毁。redis提供了一些命令,能够让我们对key设置过期时间,并且让key过期之后被自动删除。

1.设置值时直接设置有效时间:

         EX 表示以秒为单位

        PX表示以毫秒为单位    EX,PX不区分大小写

        set name  jim EX 30  设置失效时间为30秒

        ttl 键 查看剩余时间(秒)   

        pttl 键 查看剩余时间(毫秒)  

2.设置值后设置有效时间:

        expire 键 时间(秒)

        pexpire 键 时间(毫秒)

SpringBoot集成使用Redis

概述:

        Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载。Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作。

spring-data-redis针对jedis提供了如下功能:

        1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类.

        2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口.

                ValueOperations:简单K-V操作

                SetOperations:set类型数据操作

                ZSetOperations:zset类型数据操作

                HashOperations:针对map类型的数据操作

                ListOperations:针对list类型的数据操作

        3.将事务操作封装,有容器控制。

        4.针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)

        JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制.

        StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。

        JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。

搭建:

        1.添加redis依赖

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

        2.配置连接redis

spring:
  redis:
    host: 192.168.31.100
    port: 6379
    password: 111
    database: 0
    pool:
     max-active: 8  # 连接池最大连接数(使用负值表示没有限制)
     max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
     max-idle: 8 # 连接池中的最大空闲连接
     min-idle: 0 # 连接池中的最小空闲连接
     timeout: 5000ms # 连接超时时间(毫秒)

        3.注入RedisTemplate

@Autowired
RedisTemplate redisTemplate;

        4.测试

redisTemplate.opsForValue().set("name", "aa");
redisTemplate.opsForValue().set("users", users,10*1000, TimeUnit.MILLISECONDS);
redisTemplate.hasKey("name");
redisTemplate.opsForValue().get("name");
redisTemplate.delete("users");

Redis线程模型

1.Redis 是单线程模型还是多线程模型?
        Redis6.x 之前是真正意义上的单线程, 对外提供的键值存储服务的主要流程是单线程,也就是
网络 IO 和数据读写是由单个线程来完成的.Redis6.x 引入的多线程指的是网络请求过程采用了多线
程,而键值对读写命令仍然是单线程处理的,所以 Redis 依然是并发安全的,也就是只有网络请求
模块和数据操作模块是单线程的,而其它的持久化、集群数据同步等,其实是由额外的线程执行。
2. 为什么设计为单线程模型速度也很快
        由于 Redis 是基于内存的操作,查找和操作的时间复杂度都是 0(1),因此 CPU并不是
Redis 的瓶颈。Redis 的瓶颈很可能是机器内存或网络带宽的大小。既然单线程易于实现并且 CPU
不会成为瓶颈,那采用单线程解决方案是合乎逻辑的了。
        1)基于内存操作:Redis 的所有数据都在内存中,因此所有的运算都是内存级别的,所以它
的性能比较高。
        2)数据结构简单:Redis 的数据结构是为自身专门量身打造的,而这些数据结构的查找和操
作的时间复杂度都是 O(1)
        3)多路复用和非阻塞 I/O:Redis 使用 I/O 多路复用功能来监听多个 socket连接客户端,这
样就可以使用一个线程来处理多个情况,从而减少线程切换带来的开销,同时也避免了 I/O 阻塞操
作,从而大大地提高了 Redis 的性能
        4)避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,
这就省去了多线程切换带来的时间和性能上的开销,而且单线程不会导致死锁的问题发生。
  全局 hash 表
 
        
        hash 可以在 O(1)的时间内计算出 hash 值并且找到对应的 entry 位置,entry里面是一个一个
key 指针和 value 指针,其实还有其他信息。这也是 redis 之所以性能高的原因之一。

Redis 持久化 

概述:

        Redis 是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也
容易发生丢失。Redis 还为我们提供了持久化的机制,分别是RDB(Redis DataBase)和
AOF(Append Only File)。
RDB 方式:
        
        RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方
式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为
dump.rdb。 在我们安装了 redis 之后,所有的配置都是在 redis.conf 文件中,里面保存了 RDB 和
AOF 两种持久化机制的各种配置。当符合一定条件时 Redis 会自动将内存中的数据进行快照并持
久化到硬盘。
触发快照的时机
        save 的规则满足的情况下,会自动触发 rdb 规则
                        
                        redis.conf
        
        save:这里是用来配置触发 Redis 的 RDB 持久化条件,也就是什么时候将内存中的数据保存
到硬盘。比如"save m n"。表示 m 秒内数据集存在 n 次修改时,自动触发 bgsave
        
如下配置:
                save 900 1 :表示 900 秒钟内至少 1 个键被更改则进行快照。
                save 300 10 :表示 300 秒内至少 10 个键被更改则进行快照。
                save 60 10000 :表示 60 秒内至少 10000 个键被更改则进行快照。
如果不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。
        flushall 命令,情况所有 redis 数据,生成一个空的 rdb 文件(无意义)
        退出 redis,也会产生 rdb 文件, 命令: shutdown save
        关机后下次启动 redis 会自动将文件中的数据还原到内存中
AOF 方式
        以日志的形式来记录每个写操作,将 Redis 执行过的所有指令记录下来(读操作不记录),
只许追加文件但不可以改写文件,redis 启动之初会读取该文件重新构建数据,换言之,redis 重启
的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
开启方式:
        修改 redis.conf 配置文件,开启 AOF 机制
        1.appendon1y no        #默认是不开启 aof 模式的,改为 yes 开启。
        2.appendfilename appendonly.aof #默认的文件名是 appendonly.aof,可以通过
appendfilename 参数修改
        3. AOF 同步机制
                
                appendfsync always        #每次修改都会 sync。消耗性能
                 appendfsync everysec #每秒执行一次 sync,可能会丢失这 1s 的数据(默认)
                重启 redis 生效

Redis 事务

        概述:
                
                Redis 事务本质是一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过
程的中,会按照顺序执行。
                所有的命令在事务中,并没有直接被执行。只有发起执行 exec 命令的时候才会执行。
                事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。但是事务不保证同
一事物中多条命令执行的原子性,即使命令有错误也会添加到队列中,执行报错也不影响其他命令执
行。
                redis 的事务操作:
                        
                        开启事务(multi)
                        执行命令, 命令入队(.....)
                        执行前可以放弃事务(discard)
                        执行事务(exec)
                实例:
                        
                        multi 开启事务
                        
                        set a aa         添加命令
                        set b bb         添加命令
                        incr b         添加命令
                        exec         执行事务

主从复制

概述:
        
        主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点
(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。
        使用一个 Redis 实例作为主机,其余的作为备份机。主机和备份机的数据完全一致,主机支
持数据的写入和读取等各项操作,而从机则只支持与主机数据的同步和读取。也就是说,客户端可
以将数据写入到主机,由主机自动将数据的写入操作同步到从机。主从模式很好的解决了数据备份
问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取
数据的命令发送给不同的从机执行,从而达到读写分离的目的。
主从复制的作用主要包括:
        1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
        2.故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是
一种服务的冗余。
        3.负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供
读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负
载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发
量。
        4. 高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施 的基础,因此
说主从复制是 Redis 高可用的基础。
主从复制配置
        1. 主从复制时只需要配置从库即可,其默认为主库模式.
        2.打开 redis 客户端登录,使用命令 info replication 查看.
主从复制可以搭建真集群,也可以搭建伪集群.真集群就是有多台主机,每台主机安装一个 redis.伪集
群就是在一台主机上复制多份配置,修改其端口,运行多个redis 实例.配置方式两者相同。
主从配置实例
        1.复制多份配置文件,一主二从

        2.主机配置

bind 0.0.0.0 #任何 ip 都可以访问
daemonize yes 后台运行
pidfile /var/run/redis_6379.pid #进程号文件
logfile "6379.log" #日志文件 注意文件名修改只是为了区分
dbfilename dump6379.rdb #数据文件
requirepass root #主机密码

         3.从机配置

#bind 注释
daemonize yes 后台运行
pidfile /var/run/redis_6380.pid #进程号文件
logfile "6380.log" #日志文件 注意文件名修改只是为了区分
dbfilename dump6380.rdb #数据文件
replicaof <masterip>主机 ip <masterport>主机端口
masterauth <master-password>主机密码
从机进入客户端模式 ./redis-cli -p 从机端口
        进入客户端,使用 info replication 命令查看模式。
主机:

从机:

 

测试主写从读

 

主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依旧
可以直接获取到主机写的信息。

哨兵机制

概述:

        哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为

进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个

Redis 实例。

 单哨兵

哨兵集群

Key 过期策略

        1. 立即删除。在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理
器自动执行键的删除操作。立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过
期后马上被删除,其所占用的内存也会随之释放。但是立即删除对 cpu 是最不友好的。因为删除
操作会占用 cpu 的时间.
        2.惰性删除。惰性删除是指,某个键值过期后,此键值不会马上被删除,而是等到下次被使用
的时候,才会被检查到过期,此时才能得到删除。所以惰性删除的缺点很明显:浪费内存。dict 字典
和 expires 字典都要保存这个键值的信息。
        3.定时删除。每隔一段时间,对 expires 字典进行检查,删除里面的过期键。可以看到,第二
种为被动删除,第一种和第三种为主动删除,且第一种实时性更高。每隔一段时间执行一次删除操
作,并通过限制删除操作执行的时长和频率,来减少删除操作对 cpu 的影响。另一方面定时删除
也有效的减少了因惰性删除带来的内存浪费。
redis 使用的过期键值删除策略是:惰性删除加上定期删除,两者配合使用。

缓存穿透、缓存击穿、缓存雪崩

1.缓存处理流程:
前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新
缓存,并返回结果,数据库也没取到,那直接返回空结果。

 

缓存穿透 

        key 对应的数据在数据库中并不存在,每次针对此 key 的请求从缓存获取不到,请求都会到
数据库,从而可能压垮数据库。比如用一个不存在的用户 id 获取用户信息,不论缓存还是数据库
都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
        数据库没有,缓存没有.
解决办法:
        1.将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。这种情况
我们一般会将空对象设置一个较短的过期时间。
        2.对参数进行校验,不合法参数进行拦截。
缓存击穿
        某个 key 对应的数据库中存在,但在 redis 中的某个时间节点过期了,此时若有大量并发请求
过来,这些请求发现缓存过期,都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可
能会瞬间把后端 DB 压垮。
解决办法:
        1.热点数据设置永不过期
        2.加锁:上面的现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数
据的请求上使用一个互斥锁来锁住它 其他的线程走到这一步拿不到锁就等着,等第一个线程查询
到了数据,然后将数据放到 redis 缓存起来。后面的线程进来发现已经有缓存了,就直接走缓存。

缓存雪崩 

        缓存雪崩是指,在高并发情况下,大量的缓存失效,或者缓存层出现故障。于是所有的请求都会

达到数据库,数据库的调用量会暴增,造成数据库也会挂掉的情况。

 

解决方法:
        1.随机设置 key 失效时间,避免大量 key 集体失效。setRedis(Key,value,time +
Math.random() * 10000);
        2.若是集群部署,可将热点数据均匀分布在不同的 Redis 库中也能够避免 key全部失效问题
        3.不设置过期时间
        4.跑定时任务,在缓存失效前刷进新的缓存。
总结:
        雪崩是大面积的key缓存失效;穿透是redis里不存在这个缓存key;击穿是redis某一个热点
key 突然失效,最终的受害者都是数据库。

对于“Redis 宕机,请求全部走数据库”这种情况,我们可以有以下的思路:
事发前: 实现 Redis 的高可用(主从架构+Sentinel(哨兵),尽量避免 Redis挂掉这种情况发生。
事发中: 万一 Redis 真的挂了,我们可以设置本地缓存(ehcache)+限流,尽量避免我们的数据库
被干掉(起码能保证我们的服务还是能正常工作的)
事发后: redis 持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。
         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值