Redis入门学习(一)

一、 启动

1 基本操作

虚拟机中开启服务器:redis-server /etc/redis.conf (已将redis.conf复制了一份,使用这个)
查看进程:ps -ef | grep redis
开启客户端:redis-cli
测试连通:ping
关闭Redis服务:shutdown
退出:exit
(强制退出:kill -9 19812)

2 性能测试

redis-benchmark:Redis官方提供的性能测试工具(位于cd /usr/local/bin下),参数选项如下:

img

测试:100个并发连接 100000请求

打开redis-server,不需要开启redis-cli,输入:redis-benchmark -h localhost -p 6379 -c 100 -n 100000

[外链图片转存失败,源站可能有防盗链机制,å»ºè®®å°†å›¾ç‰‡ä¿å­˜ä¸‹æ¥ç›´æŽ¥ä¸Šä¼ (img-plMshjFg-1597890996515)(狂神说 Redis.assets/image-20200813114143365.png)]

3 基础命令

Redis 命令不区分大小写,键值区分大小写

基础命令:

  • exists key:判断键是否存在
  • set name jack: 设置 key-value
  • keys * : 查看当前数据库所有key
  • del key:删除键值对
  • move key db:将键值对移动到指定数据库
  • expire key second:设置键值对的过期时间
  • ttl name: 查看key的过期剩余时间
  • type key:查看value的数据类型

数据库命令:

redis默认有16个数据库,默认使用的第0个,16个数据库为:DB 0 ~ DB 15

select n:切换到DB n
dbsize:可以查看当前数据库的大小,与key数量相关。
**keys *** :查看当前数据库中所有的key。
flushdb:清空当前数据库中的键值对。
flushall:清空所有数据库的键值对。

4 基础知识

Redis是单线程的,Redis是基于内存操作的。
所以Redis的性能瓶颈不是CPU,而是机器内存和网络带宽。

Redis为什么单线程还这么快?误区1:高性能的服务器一定是多线程的?误区2:多线程(CPU上下文会切换!)一定比单线程效率高!

核心:Redis是将所有的数据放在内存中的,所以说使用单线程去操作效率就是最高的
多线程(CPU上下文会切换:耗时的操作!),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个CPU上的,在内存存储数据情况下,单线程就是最佳的方案。

二、五大数据类型

Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理
它支持字符串、哈希表、列表、集合、有序集合位图,hyperloglogs等数据类型。
内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,
同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
链接:https://www.cnblogs.com/52yu/p/16090047.html

三、三种特殊数据类型

1 Geospatial(地理位置)

2 Hyperloglog(基数统计)

3 BitMaps(位图)

链接:https://www.cnblogs.com/52yu/p/16090047.html

四、事务

redis的单条命令是保证原子性的,但是redis事务不能保证原子性。

Redis事务本质:一组命令的集合。
事务中每条命令都会被序列化,执行过程中按顺序执行,不允许其他命令进行干扰。

一次性、顺序性、排他性,Redis事务没有隔离级别的概念

1 Redis事务操作过程

  • 开启事务(multi
  • 命令入队(一些命令)
  • 执行事务(exec
  • 取消事务(discurd)

所以事务中的命令在加入时都没有被执行,直到提交时才会开始执行,一次性完成。

127.0.0.1:6379> multi # 开启事务
127.0.0.1:6379> set k1 v1 # 命令入队
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> exec # 事务执行
=====================================
127.0.0.1:6379> multi # 开启事务
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> discard  # 放弃事务
OK
127.0.0.1:6379> EXEC 
(error) ERR EXEC without MULTI # 当前未开启事务

2 事务错误

1 代码语法错误(编译时异常)所有的命令都不执行

127.0.0.1:6379> multi
127.0.0.1:6379> set k1 v1
127.0.0.1:6379> error k1 # 这是一条语法错误命令
(error) ERR unknown command `error`, with args beginning with: `k1`, # 会报错但是不影响后续命令入队 
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors. # 执行报错
127.0.0.1:6379> get k1 
(nil) # 其他命令并没有被执行

2 代码逻辑错误 (运行时异常) 其他命令可以正常执行 >>> 所以不保证事务原子性

虽然中间有一条命令报错了,但是后面的指令依旧正常执行成功了。
所以说Redis单条指令保证原子性,但是Redis事务不能保证原子性。

127.0.0.1:6379> set k1 "str"  # k1的值为字符串,不能增加
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1  # 这条命令逻辑错误(对字符串进行增量)
QUEUED
127.0.0.1:6379> get k1  
QUEUED
127.0.0.1:6379> exec
1)  (error) ERR value is not an integer or out of range  # 运行时报错
2)  "v2"    # 其他命令正常执行

3 监控(悲观锁 乐观锁)

悲观锁:
很悲观,认为什么时候都会出现问题,无论做什么都会加锁

乐观锁:
很乐观,认为什么时候都不会出现问题,所以不会上锁!
更新数据的时候去判断一下,在此期间是否有人修改过这个数据
获取version,更新的时候比较version

使用watch key监控指定数据,相当于乐观锁加锁。

127.0.0.1:6379> set money 100 # 设置余额:100
127.0.0.1:6379> set use 0 # 支出使用:0

127.0.0.1:6379> watch money # 监视money (上锁)

127.0.0.1:6379> multi
127.0.0.1:6379> DECRBY money 20
127.0.0.1:6379> INCRBY use 20
127.0.0.1:6379> exec # 监视值没有被中途修改,事务正常执行
1) (integer) 80
2) (integer) 20

解锁获取最新值,然后再加锁进行事务。

unwatch进行解锁

注意:每次提交执行exec后都会自动释放锁,不管是否成功

五、Jedis(Java中使用Redis)

六、SpringBoot整合

七、自定义Redis工具类

链接:https://www.cnblogs.com/52yu/p/16090067.html

八、配置文件Redis.conf

1 容量单位不区分大小写,G和GB有区别
2 可以使用 include 组合多个配置问题

include /path/to/local.conf
include /path/to/other.conf

3 网络配置

bind 127.0.0.1 ip绑定
protected-mode no 保护模式,默认开启
port 6379 端口

4 日志输出级别
debug (a lot of information, useful for development/testing)
notice (moderately verbose, what you want in production probably)
loglevel notice
5 日志输出文件 logfile ""

6 持久化规则

快照,如果在规定的时间内,数据发生了几次更新,那么就会将数据同步备份到一个文件中
由于Redis是基于内存的数据库,需要将数据由内存持久化到文件中
持久化方式:RDB、AOF

# 在900秒内,至少有一个key被修改(添加),就会进行持久化操作
save 900 1
# 在300秒内,至少有10个key被修改,就会进行持久化操作
save 300 10
# 在60秒内,至少有1万个key被修改,就会进行持久化操作
save 60 10000
#如果Redis在进行持久化的时候出现错误,是否停止写入,默认为是
top-writes-on-bgsave-error yes
#是否在进行数据备份时压缩持久化文件,默认为是,这个操作会耗费CPU资源,可以设置为no
rdbcompression yes
#在保存持久化文件的同时,对文件内容进行数据校验
rdbchecksum yes
#持久化文件保存的目录,默认保存在当前目录下
dir ./

7 Security模块中进行密码设置

8 客户端连接相关

maxclients 10000  最大客户端数量
    
maxmemory <bytes> 最大内存限制
maxmemory-policy noeviction  内存达到限制值的处理策略

处理策略有以下几种:

noeviction:默认策略,不淘汰,如果内存已满,添加数据是报错。
allkeys-lru:在所有键中,选取最近最少使用的数据抛弃。
volatile-lru:在设置了过期时间的所有键中,选取最近最少使用的数据抛弃。
allkeys-random: 在所有键中,随机抛弃。
volatile-random: 在设置了过期时间的所有键,随机抛弃。
volatile-ttl:在设置了过期时间的所有键,抛弃存活时间最短的数据

9 AOF相关部分

这是Redis持久化的另一种方式,AOF,AOF模式默认不开启,Redis默认开启的是持久化模式是RDB,在大部分情况下,RDB的模式完全够用

appendonly no   默认不开启AOF
appendfilename "appendonly.aof" AOF持久化的文件名称
每秒执行一次同步,但是可能会丢失这一秒的数据

# 对于 appendfsync 它有以下几个属性 
# appendfsync always 表示每次修改都会进行数据同步,速度较慢,消耗性能
# appendfsync no 不执行同步,不消耗性能
appendfsync everysec # 数据不同步,每秒记录一次

九、持久化RDB

简介

RDB:Redis Databases
在指定时间间隔后,将内存中的数据集快照写入数据库 ;
在恢复时候,直接读取快照文件,进行数据的恢复 ;

默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。文件名可以在配置文件中进行自定义。

工作原理:。。。

触发机制

  1. save的规则满足的情况下,会自动触发rdb原则
  2. 执行flushall命令,也会触发我们的rdb原则
  3. 退出redis,也会自动产生rdb文件
# 在300秒内,至少有10个key被修改,就会进行持久化操作
save 300 10

优缺点

优点:

  1. 适合大规模的数据恢复
  2. 对数据的完整性要求不高

缺点:

  1. 需要一定的时间间隔进行操作,如果redis意外宕机了,这个最后一次修改的数据就没有了
  2. fork进程的时候,会占用一定的内容空间

十、持久化AOF

简介

AOF:Append Only File

将我们所有的命令都记录下来,history,恢复的时候就把这个文件全部再执行一遍

以日志的形式来记录每个写的操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,
换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、以及未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。

如果要使用AOF,需要修改配置文件:appendonly no yes则表示启用AOF

如果这个aof文件有错位,这时候redis是启动不起来的,我需要修改这个aof文件
redis给我们提供了一个工具redis-check-aof --fix

优缺点

优点

  1. 每一次修改都会同步,文件的完整性会更加好
  2. 每秒同步一次,可能会丢失一秒的数据
  3. 从不同步,效率最高: appendfsync everysec

缺点

  1. 相对于数据文件来说,aof远远大于rdb,修复速度比rdb慢!
  2. aof运行效率也要比rdb慢,所以我们redis默认的配置就是rdb持久化

十一、Redis发布与订阅

Redis 发布订阅是一种消息通信模式:发送者(publish)发送消息,订阅者(subscribe)接收消息。

------------订阅端----------------------
127.0.0.1:6379> subscribe channel # 订阅channel频道
Reading messages... (press Ctrl-C to quit) # 等待接收消息
1) "subscribe"  # 订阅成功的消息
2) "channel"
3) (integer) 1
1) "message" # 接收到来自channel频道的消息 "hello"
2) "channel"
3) "hello"
---------消息发布端-------------------
127.0.0.1:6379> publish channel "hello" # 发布消息到channel频道
(integer) 1
---------发布端查看活跃的频道------------
127.0.0.1:6379> pubsub channels
1) "channel"

应用:

  1. 消息订阅:公众号订阅,微博关注等等(起始更多是使用消息队列来进行实现)
  2. 多人在线聊天室

稍微复杂的场景,我们就会使用消息中间件MQ处理。

十二、Redis主从复制(集群)

十三、哨兵模式

链接:https://www.cnblogs.com/52yu/p/16090090.html

十四、缓存穿透与雪崩(工作常用!!!)

对于Redis缓存来说,它提升了应用程序的性能和效率,
并且缓存在高并发场景中起到了非常重要的作用,
如果针对数据的一致性来说,Redis的缓存就是一个非常致命的问题,这种问题有三个。

1 缓存穿透(查不到数据)

在大多数场景中,数据库里的id字段一般来说都是自增。如果说,用户发送了一个请求,会首先进入缓存,查不到,就进入数据库,进了数据库,也查不到,查不到的话,如果说访问量较少,那还好,直接返回不存在嘛,因为这种少量的缓存穿透实际上是不可避免的,但是,一旦在发送请求查询数据库的时候,主键的id字段故意给你来一个负数或者是一些远大于数据库最大id的数,而且进行巨大量的并发访问,这时候缓存中肯定是没有的,那这些请求就直接压给数据库了,数据库扛不住这么大的东西,就只能挂掉呀。

解决方案

1 布隆过滤器

对所有可能查询的参数以Hash的形式存储,以便快速确定是否存在这个值,在控制层先进行拦截校验,校验不通过直接打回,减轻了存储系统的压力。

2 缓存空对象

一次请求若在缓存和数据库中都没找到,就在缓存中存放一个空对象用于处理后续这个请求。

缺陷:存储空对象也需要空间,大量的空对象会耗费一定的空间,存储效率并不高。解决这个缺陷的方式就是设置较短过期时间
即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

2 缓存击穿(量太大,缓存过期)

相较于缓存穿透,缓存击穿的目的性更强,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到数据库,造成瞬时数据库请求量大、压力骤增。

这就是缓存被击穿,只是针对其中某个key的缓存不可用而导致击穿,但是其他的key依然可以使用缓存响应。 比如热搜排行上,一个热点新闻被同时大量访问就可能导致缓存击穿。

解决方案

1 设置热点数据永不过期

这样就不会出现热点数据过期的情况,但是当Redis内存空间满的时候也会清理部分数据,而且此种方案会占用空间,一旦热点数据多了起来,就会占用部分空间。

2 加互斥锁(分布式锁)

在访问key之前,采用setnx(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。保证同时刻只有一个线程访问。这样对锁的要求就十分高。

3 缓存雪崩

大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时数据库请求量大、压力骤增,引起雪崩。如双十一的秒杀活动

解决方案

1 redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群

2 限流降级

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。(如双十一不允许退款查询历史订单)

3 数据预热

在正式部署之前,先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。
在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

狂神:https://www.bilibili.com/video/BV1S54y1R7SB?from=search&seid=3929831479981400108
5akura:https://blog.csdn.net/weixin_43873227/article/details/106107270

posted @ 2022-04-01 23:12  yu10001  阅读(87)  评论(0编辑  收藏  举报