redis

数据库分类

关系型数据库:oracle、mysql、sql server、DB2

数据落到硬盘里,IO读写瓶颈,限制了数据规模

非关系型数据库:redis、mongoDB、ElasticSearch、Hbase、Neo4j

NoSQL(not only sql):应对超大规模和高并发场景

高性能(redis每秒写8万,读11万),将磁盘IO改为内存IO

no-relation,不保证关系数据的ACID特性

数据类型多样(不需设计数据库)

五大基本类型:string、list、set、hash、zset

三种扩展类型:geo、hyperloglog、bitmap

分为:键值型、列存储、文档型、图数据库

|-------------------------------------------------|---------------------------------------------------------------------------------|
| RDBMS | NoSQL |
| 结构化组织 SQL 数据和关系都存在单独表中 操作定义、数据定义语言 严格的一致性 基础的事务 | 不仅仅是数据 没有固定的查询语言 键值对存储、列存储、文档存储、图形数据库(社交关系) 最终一致性 CAP理论和BASE (异地多活) 高性能、高可用、高扩展 |

实践中常把RDBMS和NoSQL结合使用

redis特点

redis = REmote DIctionary Server 远程字典服务

纯内存操作

数据存储在内存,无磁盘IO开销

单线程模型

redis 6.0+ 多线程网络IO,命令执行仍单线程

效率高,无锁竞争

IO多路复用

epoll监听多个socket,非阻塞IO

高效数据架构

底层数据结构,高度优化

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

不建议存储敏感(可靠性要求较高)数据,内存断电易失

redis官网

Redis - Real-time data for agents & appshttps://redis.io/

命令帮助

Redis 8.8 Commands Reference | Docshttps://redis.io/docs/latest/commands/redis-8-8-commands/

获取源码包

Index of /releases/https://download.redis.io/releases/wget https://download.redis.io/releases/redis-8.8.1.tar.gz

redis安装

rocky linux 10.1

Install Redis Open Source | Docs

dnf默认源里没有redis,使用remi,Remi 是 RHEL 系 Linux 上最受欢迎的第三方软件源之一,提供了大量更新、更全的软件包

dnf install -y epel-release

dnf install -y https://rpms.remirepo.net/enterprise/remi-release-10.rpm

dnf module list redis

dnf module enable redis:remi-8.8 -y

dnf -y install redis

启动redis服务

测试

redis-cli

127.0.0.1:6379> ping

PONG

配置文件:/etc/redis/redis.conf

默认端口:6379

配置文件

/etc/redis/redis.conf 配置文件位置

include /etc/redis/modules/*.conf 包含子配置文件

bind 127.0.0.1 绑定的IP地址,可设置为bind 0.0.0.0监听所有IP

protected-mode yes 保护模式,开启后默认用户没有密码,仅允许从127.0.0.1登录

daemonize no 是否以守护进程运行

pidfile /run/redis/redis.pid 如果以后台守护进行运行,就需要指定pid文件

loglevel notice 日志级别,生产环境常用notice

logfile /var/log/redis/redis.log 日志文件

databases 16 数据库数量

always-show-logo no 是否总显示logo标志,以daemon启动时

save 3600 1 300 100 60 10000 持久化(内存型数据库,不保存断电丢数据),默认1小时改变1次、5分钟改变100次、1分钟改变10000次自动保存

stop-writes-on-bgsave-error yes 持久化失败,是否继续工作

rdbcompression yes 是否压缩rdb文件,消耗一定CPU资源

rdbchecksum yes 保存rdb文件时是否进行校验

dir /var/lib/redis rdb文件保存的位置

requirepass foobared 设置密码为foobared

maxclients 10000 最多客户端数量

maxmemory <bytes> 最大内存用量

maxmemory-policy noeviction 达到最大内存后的策略,永不过期,只报错

appendonly no aof持久化是否开启

appendfilename "appendonly.aof" aof文件名

appenddirname "appendonlydir" aof文件目录

appendfsync always 每次修改都同步

appendfsync everysec 每秒同步,可能丢失1s数据

appendfsync no 不同步,操作系统自己同步

密码设置

默认没有密码

命令终端修改密码

config set requirepass "123456" 设置密码

config rewrite 保存到配置文件

修改配置文件改密码

requirepass foobared 设置密码为foobared

设置密码后连接方式

redis-cli -u redis://default:123456@127.0.0.1:6379/0

redis-cli -h 127.0.0.1 -p 6379 --user default -a 123456

redis-cli -h 127.0.0.1 -p 6379 -a 123456 可不写默认用户

运行redis-cli后输入auth yourpassword 这种方式命令不自动补齐,无自动提示

操作命令

redis-cli -h 127.0.0.1 -p 6379 默认参数可不写,直接redis-cli

登录:-h 指定服务器,默认127.0.0.1, -p 指定端口,默认6379

默认16个数据库,默认使用0号库,通过select num切换数据库

SELECT 1

查询当前库中所有键

KEYS * 查看所有key

SET user1 zhang 增加key

GET user1 获取key

DEL user1 删除key

EXISTS user1 查询key是否存在

命令关键字大小写都可以,键值需严格区分大小写

MOVE user1 1 将key从当前库迁至1号库

set k1 v1 ex 10 新建key时直接设置到期时间

EXPIRE user1 60 设置key的超时时间,超时后删除

TTL user1 查询key的超时时间

type user1 查看key的类型

flushdb 清空当前库

flushall 清空所有库 默认16个库,编号0 - 15

不同库里的key可以一样,同一库里的key不能一样

key类型

string 字符串类型,默认类型

APPEND k1 hello 向字符串追加内容(存在则追加内容,不存在则新建)

STRLEN k2 获取字符串长度

set salary 0

incr salary 增加key,加1

decr salary 减少key,减1

INCRBY salary 1000 增加key,指定增量

DECRBY salary 500 减少key,指定减量

set k1 "hello,linux world!"

getrange k1 0 3 获取key的0至3号字符

getrange k1 0 -1 获取key所有字符,相当于get key

GETRANGE k -3 -1 -1表示最后一个,-3表示倒数第3个,取最后3个

setrange k1 0 hH 从指定位置开始,顺序替换字符

SETRANGE a 40 "new add" 字符串长度不够的话,会在后面补x00

setex key1 60 "expire after 60s" 设置key的过期时间和值,key是否存在都可以设置,存在时覆盖原值

set a "aaa" set a "bbb" 使用set会覆盖key已存在值

setnx a "ccc" setnx命令当key存在时不会覆盖原值,key不存在时新建

mset k1 v1 k2 v2 k3 v3 一次增加多个key和value

mget k1 k2 k3 一次获取多个key

msetnx k1 v1 k2 v2 当key不存在时,设置多个key 原子性,同时成功或失败

msetex 3 k1 v11 k2 v22 k3 v33 ex 30 同时设置多个key过期时间和值,3是key数量,与后面k和v对数一致

mset user:1:name zhang user:1:age 19

set user:1 {name:zhang,age:18}

getset a AA 先获取key的值,再设置新值,key不存在时新建

list 可以做栈、队列、阻塞队列

left 对应显示顺序的顶部,right 对应显示顺序的底部

lpush list one two three 向list中添加one two three,从底部添加

lpush list four

exists list 判断是否存在

type list 查看类型

lrange list 0 -1

rpush list zero 从顶部添加

lrange list -2 -1 取最先放进来的2个

lpop list 1 从顶部移出1个

rpop list 1 从底部移出1个

del list 删除列表

lindex list -1 取出最后一个,通过下标获取值,没有rindex

lindex list -3 取出倒数第3个

LINDEX list 0 取出第1个,顶部开始

LLEN list 获取列表的长度

lrem list 1 two 从列表中移出1个two

lrem list 3 five 从列表中移出3个five,数量不够时全部移除

lrem list 2 five 从列表移出2个five,从顶部开始移

ltrim list 1 1 只保留序号为1的值

LTRIM mylist 2 3 只保留序号为2和3与之间的值,也就是只留2和3

LTRIM mylist 1 4 掐头去尾,只保留下标序号为1和4与之间的值

rpoplpush list newlist 从列表list中移除底部一个值,并移动到新列表newlist中

lset list 2 four 修改列表下标为2的值为four,只能修改已存在的下标

linsert list before one zero 在one值前插入zero

linsert list after zero zero.five 在zero后插入新值

set集合

集合中元素不能重复

sadd myset hello world 新建集合myset,包含hello和world两个元素

exists myset

type myset

smembers myset 查看集合元素

sismember myset hello 判断集合myset中是否有hello元素

scard myset 查看集合中元素数量

srem myset cpu 移除cup元素

srandmember myset 2 从集合中随机抽2个元素

spop myset 2 随机

SMOVE myset myset1 qian 将元素qian从myset移动到myset1

交集、并集、差集

SDIFF set1 set2 差集

SDIFF set2 set1 差集

SINTER set1 set2 交集

SUNION set1 set2 并集

hash适合对象存储

存储经常变更的数据

hset user:989 name zhangsan age 28 gender male class 3 新增hash类型:key = filed value

hmset user:989 country china privence beijing

hget user:989 age 获取hash key,指定单个filed

hmget user:989 country name 获取hash key,指定多个filed

hgetall user:989 获取hash key所有filed和value

hdel user:989 street class 删除多个指定filed

HLEN user:989 获取hash key长度,一对filed和value为1个长度

HEXISTS user:989 name 判断filed是否存在

HKEYS user:989 获取所有filed

HVALS user:989 获取所有value

HINCRBY user:989 age 2 增加对应field的value

HINCRBYFLOAT user:989 age 0.5 增加对应field的value,带小数

HSETNX user:989 test 12345 不存在则创建field

zset有序集合

在set的基础上增加了一个值,k1 score1 v1,可将score用于排序

zadd myzset 19999 zhangsan 30000 lisi 10000 wangwu 18888 zhaoliu

type myzset 判断类型

exists myzset 判断是否存在

zcard myzset 判断长度

zrange myzset 0 -1 查看有序集合所有元素,默认按score大小正序排列

zrange myzset 0 -1 withscores 按score正序排列查看有序集合所有元素,并显示score

zrange myzset 0 -1 rev 查看有序集合所有元素,按score大小逆序排列

zrange myzset 0 -1 rev withscores 按score逆序排列查看有序集合所有元素,并显示score

ZREVRANGE myzset 0 -1 withscores 按score逆序排列查看有序集合所有元素,并显示score

zrem myzset zhaoliu wangwu 删除指定元素

ZRANGEBYSCORE myzset -inf +inf 按score从小到大排序,不显示score

ZRANGEBYSCORE myzset -inf +inf withscores 按score从小到大排序,显示score

ZREVRANGEBYSCORE myzset +inf -inf withscores 按score从大到小排序,显示score

ZRANGEBYSCORE myzset -inf 15000 withscores 15000及以下的

ZRANGEBYSCORE myzset 15000 +inf withscores 15000及以上的

ZCOUNT myzset 15000 30000 获取score在指定区间的元素数量

zrem myzset laohu 删除指定元素

ZREMRANGEBYSCORE zset 14000 18000 删除score处于指定范围的元素

ZPOPMAX myzset 1 删除score值最高的一个

zpopmin myzset 1 删除score值最低的一个

geospatial地理位置

geospatial底层是zset

朋友定位、附近的人、打车距离

【经纬度查询】在线地图经度纬度查询|经纬度地名坐标转换https://map.jiqrxx.com/jingweidu/

geoadd china:city 116.72447000 39.90504700 beijing 117.34497070 39.29179704 tianjin

geoadd china:city 121.47362900 31.23039300 shanghai 106.55058200 29.56345000 chongqing

geoadd china:city 108.94042969 34.34343607 xian 87.61596680 43.82660135 wulumuqi

GEOPOS china:city chongqing tianjin 获取指定城市的坐标

geodist china:city beijing tianjin KM 获取两在个城市间的距离,指定单位KM

geodist china:city beijing wulumuqi km

GEORADIUS china:city 116.72 39.90 100 km withdist 查询指定经纬度100KM内的城市

GEORADIUS china:city 116.72 39.90 1000 km withdist withcoord 显示距离和经纬度

GEORADIUSBYMEMBER china:city shanghai 1200 km withdist withcoord

GEOHASH china:city beijing xian 将经纬度转换为固定长度的hash字符串

可以使用zrange列出所有元素,zrem删除指定元素

hyperloglog基数统计

基数:不重复的元素数量

只记账 "大概有多少个不同元素",不留名单,事后没法把名单拿出来。

比如,网页UV,一个人访问同一网站多次,对访问量来说,只算1个用户

pfadd key1 a b c d e f g h i j k l

pfadd key2 a c e g j l m n o p q r s t

pfcount key1

pfcount key2

pfcount key1 key2 合并统计key1和key2不重复的

pfmerge mykey key1 key2 合并key1和key2为新的mykey,合并时去重

pfcount mykey

bitmaps位存储

只有0和1,方便统计。是/不是

下列设置周1到周7的打卡记录

setbit sign 1 1

setbit sign 2 1

setbit sign 3 1

setbit sign 4 0

setbit sign 5 1

setbit sign 6 0

setbit sign 7 0

getbit sign 1 获取打卡记录

BITCOUNT sign 0 -1 统计一周打卡天数

事务

ACID:mysql数据库的特性

事务:一组命令的集合

原子性:要么同时成功,要么同时失败

redis单条命令保证原子性,但事务不保证原子性。一次性、顺序性、排他性执行

redis事务没有隔离级别的概念

所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才会执行

redis的事务

开启事务(multi)

命令入队(按顺序输入命令)

执行事务(exec)

正常执行事务:multi --- **** --- exec

放弃事务: discard

运行异常:

命令异常时(缺关键参数)放弃所有

命令能执行(但参数不匹配),事务仍可执行,错误的没有结果

监控watch,相当乐观锁

悲观锁:

认为无论什么时间都会出问题,无论做什么都加锁

乐观锁:

认为无论什么时间都不会出问题,只有更新数据时才加锁

正常执行

异常情况

set money 100

set out 0

watch

multi

DECRBY money 20

INCRBY out 20

此时另一客户端修改了money的vaule,set money 120

exec 执行时就不会执行

以上执行时,如果没有使用watch,则即使另一客户端做了修改,仍按原来值执行。

unwatch 取消锁,如果事务执行失败,就先解锁

Jedis

官方推荐的java连接工具

持久化

内存数据断电丢失数据,必须持久化存储到磁盘

RDB

在指定的时间间隔将内存数据集快照写入磁盘,也就是快照,恢复时是将快照文件直接读到内存里。

redis单独创建一个fork子进程进行rdb持久化

rdb效率高,但可能丢最后一次快照后新修改的数据

配置文件:dbfilename "dump.rdb" 保存为dump.rdb文件

触发机制:

save规则满足的情况

flushall命令触发

退出redis时触发

redis启动时会自动加载配置文件中指定位置的dump.rdb

优势:

适合大规模数据恢复

对数据完整性要求不高

缺点:

需要一定的时间间隔才保存,在此间隔修改的数据有丢失风险

fork进行会占用一定的内存空间

生产环境中可对dump.rdb进行备份

AOF

Append Only File 将所有命令都记录下来,恢复的时候将所有写命令都执行一遍

默认没有开启AOF

appendonly yes 开启aof

appendfsync everysec 每秒写一次,默认

重启redis服务,即可生效

如果aof文件错误,redis启动不了,可以用redis提供的aof修复工具修复

/usr/bin/redis-check-aof 此工具修复aof文件

/usr/bin/redis-check-aof --fix /var/lib/redis/appendonlydir/appendonly.aof.1.incr.aof

修复后可正常启动redis

优点:

每次修改都同步,文件的完整会更好 appendfsync always

每秒同步一次,可能丢失一秒数据,默认 appendfsync everysec

从不同步,效率最高 appendfsync no

缺点:

数据文件aof远大于rdb,aof修复速度慢,效率比rdb低

只做缓存,可以不使用任何持久化

同时开启rdb和aof时,优先使用aof数据载入

发布订阅

发布者 --- -- 发送信息到队列 (频道) -----订阅者从队列取信息

订阅者

发布者

主从复制

将一台redis服务器的数据,复制到其他redis服务器。前者称为master/leader,后者称为slave/follower

master以写为主,slave以读为主。80%的操作都是读操作。常用一主两从

作用:

数据空余

故障恢复

负载均衡

高可用基石

单个redis实例建议内存不超过16GB

配置:只配置从库,不用配置主库(默认为主)

info replication 查询主从复制状态

主从模式1:星形

单台master做为所有slave的主

info replication 查看主从状态

如果主库设置了密码,需要在配置参数中进行配置

从库连接主库配置:

REPLICAOF 192.168.3.198 6379 早期版本slaveof,指定master地址和端口

config set masterauth "123456" 设置连接master的密码

上面配置重启服务后就失效,需要写入配置文件,直接编辑配置文件,或使用命令写入

config rewrite

master上查看主从信息

退出slave模式

主从模式2:链式

链式与网络模式无关

slave1做为master1的从,但做为slave2的主

master1

slave1 master2

slave2

复制原理

全量复制:所有数据,重新连接到master就执行全量复制

增量复制:增加的数据,全量复制后的数据变更

生产模式(哨兵模式)

上述的两种都是手动配置,生产中都不会使用

哨兵模式可自动选举master,需要单独redis-sentinel哨兵服务监控各服务器运行状态

8.8版本已默认安装了redis-sentinel服务

单哨兵模式存在哨兵故障无备份隐患,生产中不用

生产中常用多哨兵模式

架构:

192.168.3.198 6379 master + sentinel1 26379

192.168.3.196 6379 slave1 + sentinel2 26379

192.168.3.197 6379 slave2 + sentinel3 26379

先配好redis集群

先开启对IP地址的绑定,修改配置文件 bind 127.0.0.1 -::1 192.168.3.198

从上要配置主和认证密码,并写入配置文件

主上要配置认证密码并写入配置文件,否则切换主后原主连不上新主

/etc/redis/sentinel.conf 哨兵服务配置文件

sentinel monitor mymaster 192.168.3.198 6379 2 关键配置,所有哨兵都监控master.哨兵会自动发现所有副本、自动发现其他哨兵,不需要手动填写从库和其他 sentinel 地址。

sentinel auth-pass mymaster "123456" 设置连接密码

sentinel down-after-milliseconds <master-name> <milliseconds 3000> 判断主断开时间

sentinel failover-timeout <master-name> <milliseconds 10000> 故障转移总时间

上述配置可在6秒内完成切换

sentinel notification-script <master-name> <script-path> 设置报警通知脚本

让哨兵监控指定主节点;只有至少 <quorum> 数量的哨兵一致判定主节点故障,才将其标记为 客观下线(ODOWN) 。# sentinel monitor <master-name> <ip> <redis-port> <quorum>

默认配置故障切换时间超过30秒

systemctl enable --now redis-sentinel.service 启动服务

查询哨兵服务状态

SENTINEL GET-MASTER-ADDR-BY-NAME mymaster 获取主IP地址

SENTINEL MASTER mymaster 查看主节点状态

SENTINEL REPLICAS mymaster 查看从节点状态,应列出2台

SENTINEL SENTINELS mymaster 查看除自己外所有哨兵

测试:

从主上停止redis服务 systemctl stop redis

查看主状态,显示disconnected

超时后,已选举出新的master,测试集群正常运行

当掉线的主回来后,会自动变为从,而不会抢占主

缓存穿透和雪崩

缓存穿透:查询数据库不存在的数据,请求无法命中 Redis,每次都直接打到数据库。

解决方案: 布隆过滤器、缓存空对象

缓存击穿:一个热点 Key 刚好过期,大量并发请求同时涌入数据库

解决方案:互斥锁(分布式锁)、热点 key 永不过期、过期时间随机打散

缓存雪崩:大量缓存 key 在同一时间段集中过期失效,海量请求同时涌向数据库,直接压垮 DB

解决方案:高并发核心业务:随机TTL + 本地二级缓存 + Redis高可用 + 熔断降级

相关推荐
jun_bai1 小时前
postgresql数据库免安装版安装到windows系统
数据库·postgresql
weixin_538601971 小时前
智能体测开Day33
数据库·oracle
番茄炒鸡蛋加糖2 小时前
Redis--Lua 脚本原子性与滑动窗口限流
数据库·redis·lua
瀚高PG实验室2 小时前
DELETE 条件字段缺少索引导致 SuperSync 同步严重延迟
数据库·postgresql·瀚高数据库
笃行3502 小时前
优化器凭什么改写你的 SQL:等价变换、条件调度与主流数据库的取舍
数据库
KaMeidebaby2 小时前
卡梅德生物技术快报|bli亲和力检测gst:告别批量跑胶:BLI实时酶切监测技术加速GST融合蛋白下游流程优化
前端·网络·数据库·人工智能·算法
千维百策6662 小时前
运用 SRE 原则降低生产事故影响:CRE 实战经验与可靠性优化方法
网络·数据库·人工智能
笃行3502 小时前
能跑不等于正确:生产环境不规范 SQL 的隐藏风险与编码规范
数据库
龙虾PRO3 小时前
能源与股票量化核心差异,AI全链路落地实操手册
java·面试·职场和发展
llwszx3 小时前
【Java/Go后端手撸原生Agent(第九篇):Plan-and-Execute规划模式——从“走一步看一步“到“先谋后动“】
java·python·golang·agent开发·plan模式·规划执行模式