Redis官方推荐使用的是Linux系统进行安装(win的Redis版本低,也没有维护了)所以这里是Linux的教程,Redis安装有几种,如宝塔面板(服务器)、手动按照等等。
手动安装
到官网进行下载
把下载好的文件上传到Linux系统里(本身是Linux系统忽略本小结步骤直接看3)),可以使用xftp上传
注:建议把文件上传到/usr/local/redis,因为usr目录主要是存放应用程序和文件的目录
输入命令:
cd …/usr/local/redis(进入到usr/local/redis就对了)
tar -zxvf redis-6.0.3.tar.gz(解压,解压完成用ls命令查看,如下就是完成)
cd redis-6.0.3(进入redis目录)
yum -y install gcc-c++ (安装gcc)
注意点:redis6.0以上需要升级gcc到5.3及以上,命令如下
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 “source /opt/rh/devtoolset-9/enable” >>/etc/profile
这样退出shell重新打开就是新版的gcc了
make (编译解压好的redis文件)
拓展:
编译出错时,清出编译生成的文件
make distclean
编译安装到指定目录下
make PREFIX=/usr/local/redis install
卸载
make uninstal
make install (进行redis安装)
偷懒方法:
打开xftp
复制/usr/local/redis/redis-6.0.3/redis.conf
粘贴到sr/local/bin/myconf里(myconf就自己创建)
然后双击myconf目录下的redis.conf修改内容,内容如下
命令方法:
会Linux的都应该知道怎么做了,效果和上面一样就行
redis-server myconf/redis.conf(通过myconf/redis.conf的配置文件来启动redis-server)
redis-cli -p 6379(启动客户端,通过ip:localhost 端口:6379连接)
ps: redis-cil --cluster create ip1:端口 ip2:端口 ip3:端口 …–cluster-replicas 1 客户端连接集群,后面课程
指令选项详细点这里
ping(发送ping请求,回复PONG就是完成了)
shutdwon (关闭redis服务端)
quit或者exit(提出redis客户端)
http://c.biancheng.net/view/4507.html spring配置 https://docs.spring.io/spring-data/redis/docs/2.3.0.RELEASE/reference/html/#reference 官网
命令 | 功能 |
---|---|
【key】 | |
keys * | 查看数据库全部key |
randmokey | 获取随机一个key |
【查看类型】 | |
type key | 查看key的类型 |
【数据库大小】 | |
DBSIZE | 查看有多少key |
【清除】 | |
FLUSHDB | 清除当前数据库的数据 |
FLUSHALL | 清除全部数据库的数据(会持久化) |
【切换数据库】 | |
SELECT id | 切换指定id数据库(不超过databases配置) |
【修改/获取配置】 | |
CONFIG SET key value | 修改key等于value(key就是配置项名) |
CONFIG GET key | 获取配置项的值 |
【快照】 | |
save | 立即执行快照(堵塞当前线程) |
bgsave | 立即执行快照(不堵塞) |
【密码】 | |
auth xxx | 提交密码,登入 |
【停止服务】 | |
showdown | 停止redis服务器 |
exit | 结束客户端连接 |
数据命令 | 功能 |
---|---|
【String】 字符串类型 | |
set key value | 存储(创建) |
get key value | 获取 |
del key | 删除 |
getset key value | 先获取,再存储 |
mset k1 v1 k2 v2 … | 存储多个key |
msetnx k1 v1 k2 v2… | 存储多个key,如果其中某个key存在则创建则一起失败(原子性) |
mget k1 k2 k3… | 获取多个key |
append key value | 追加value到指定key |
getrange key x y | 获取指定范围的字符串 |
setrange key x value | 从指定的位置开始替换成指定的值 |
incr key | 自增一 |
decr key | 自减一 |
incrby key x | 设置自增量,并执行一次 |
decrby key x | 设置自减量,并执行一次 |
setex key | 设置过期时间 |
setnx key | 不存在就创建,存在创建失败 |
strlen key | 获取字符串长度 |
【hash】 哈希类型 | |
hset key key-field key-value | 存储 |
hmset k1 k1-k k1-v k2 k2-k k2-v… | 存储多个 |
hget key map-field … | 获取指定字段和值 |
hgetall key | 获取全部字段和值 |
hkeys | 获取全部字段 |
hvals | 获取全部值 |
hdel key key-field | 删除指定字段 |
hexists key key-field | 判断字段是否存在 |
hincrby key key-field x | 设置自增量 |
hdecrby key key-field x | 设置自减量 |
hsetnx key key-field key-value | 不存在就创建,存在创建失败 |
hlen key | 获取长度 |
【list】 (list 有序可重复) | |
lpush key value | 存储到第一位 |
rpush key value | 存储到最后一位 |
linsert key before v1 v2 | 把v2添加到v1前面 |
linsert key after v1 v2 | 把v2添加到v1后面 |
lset key x value | 更新(替换)指定索引的值为value |
lrange key x y | 获取指定范围的值(x=0,y=-1获取全部) |
lindex key x | 获取指定索引的值 |
lpop key | 删除第一位 |
rpop key | 删除最后一位 |
lrem key x value | 删除指定的value(存在一样的value,x可以指定删除几个) |
rpoplpush key newkey | 把最后一位移动到新的list里 |
ltrim key x y | 保留(截取)指定索引范围的值 |
llen key | 获取list长度 |
【set】 (set 无序不可重复) | |
sadd key value | 存储 |
smembers key | 获取全部值 |
sismember key value | 判断指定value是否存在 |
scard key | 获取元素的个数 |
srem key value | 删除指定元素(value) |
srandmember key x | 随机获取x个元素(x省略则为1) |
spop key | 随机移除元素 |
smove k1 k2 value | 移动k1的value到k2集合里 |
sdiff k1 k2 | 差集(k1元素在k2里不存在的元素) |
sinter k1 k2 | 交集(k1和k2相同的元素) |
sunion k1 k2 | 并集(k1和k2合成一个集合,去除重复项) |
【sortedset】 (sortedset 有序不重复(按分数排)) | |
zadd key 分数 value | 存储 |
zrange mysort x y | 获取指定索引范围的值(x:0 y:-1获取全部值) |
zrange mysort value withscores | 获取指定值以及携带的分数 |
zrem key value | 删除 |
zrangebyscore key -inf +inf withscores | 指定最小到最大值范围分数进行降序排序(withscores:结果返回带分数) |
zrevrange key -inf +inf | 指定最小到最大值范围分数进行升序排序 |
zcount key x y | 获取指定分数范围的成员数量 |
zcard key | 获取有序集合中的个数 |
【通用】 | |
exists key | 查看是否存 |
type key | 查询类型 |
keys /正则表达式/ | 查询指定键 |
del key | 删除指定键 |
move key id(数据库id) | 移动指定键到指定数据库 |
expire key time | 设置key的过期时间(秒) |
ttl key 30 | 查看距离过期的时间 |
geospatial:将指定的地理空间位置(纬度、经度、名称)添加到指定的key中,可以推算地理位置的信息,两地之间的距离,方圆几里的人,geo底层是zset集合(sortedset),注:无法添加两级
数据命令 | 功能 |
---|---|
【geospatial】 | |
geoadd key 纬度 经度 名称 | 存储地理空间位置 |
geopos key 名称 … | 获取地理空间位置(…允许多个) |
geodist key 名称1 名称2 | 获取两地之间的距离 |
georadius key 纬度 经度 半径km | 获取指定经纬度半径内存在的地理空间位置 withcoord:返回携带经纬度 withdist:返回携带两地之间的距离 count x:返回最多x个 |
georandiusbymember key 名称 维度 经度 半径km | 获取指定元素名称半径内存在的地理空间位置 |
geohash key 名称… | 获取地理空间位置(返回的经纬度是11位Geohash字符串) |
zrem key 名称 | 删除地理空间位置 |
HyperLogLog:是一种算法,它提供了不精确的去重计数方案,优秀大佬博客
数据命令 | 功能 |
---|---|
pfadd key v1 v2… | 存储多个元素 |
pfcount key | 统计元素的基数数量(就是统计数量) |
pfmerge newkey key1 key2 | 并集方式合并key1和key2生成新的newkey |
Bitmap:位存储,使用场景:打卡、活跃度、登入状态等等,只要0和1能表示的就行,只能存储0或1的值
数据命令 | 功能 |
---|---|
setbit key offset value | 存储键的第offset个位的值(从0开始) |
getbit key offset | 获取第offset个位的值 |
bitcount key 开始值 结束值 | 统计指定范围内值为1 的个数 |
bitop and destkey key [key…] | 多个key取与,并把结果存入目标destkey |
bitop or destkey key [key…] | 多个key取或,并把结果存入目标destkey |
bitop not destkey key [key…] | 多个key取非,并把结果存入目标destkey |
bitop xor destkey key [key…] | 多个key取异或,并把结果存入目标destkey |
bitpos key targetBit 开始值 结束值 | 第一个值为targetBit的偏移量(我不懂),不包含开始值 |
命令 | 功能 |
---|---|
redis-cli [可选项] | 集群命令 |
–cluster create ip1:端口 ip2:端口 ip3:端口 | 创建集群主从节点 |
–cluster create x x x --cluster-replicas x | 创建集群并给主节点分配x个从节点 |
–cluster add-node 新节点 要连接的节点 | 为一个指定集群添加新节点 |
–cluster add-node x x --cluster-slave | 为一个指定集群添加从节点 |
–cluster add-node x x --cluster-slave --cluster-master-id x | 为一个指定集群添加从节点给指定id的主节点 |
–cluster del-node ip:端口 or id | 删除节点(删除不了主节点) |
–cluster info | 查看集群信息 |
Redis单条命令是保存原子性的,但是事务不保证原子性且没有隔离级别的,Redis没有隔离级别(隔离性)
Redis事务本质:一组命令的集合,会按照先后顺序执行(队列),执行过程中是不会被干扰(其他客户端提交的命令请求不会插入到事务执行命令序列中)
命令 | 功能 |
---|---|
multi | 开启事务 |
exec | 执行事务 |
discard | 放弃事务 |
事务执行过程:
开启事务(multi)命令后就会生成一个队列缓存,把我们接下来的命令进行存储(不执行),只有当执行事务(exec)命令时才开始执行。未执行事务时是可以放弃该次事务(discard)的
事务编译型异常:
代码有问题或命令有问题(类似于java编译性错误),在执行(exec)命令时所有存储的命令是不会执行的(也可以说是放弃掉)
事务运行时异常:
代码和命令没问题,但是存在逻辑不合法(语法性、命令性)问题,事务执行时只会放弃出问题的命令,其它的命令依然执行
如:在一个key里存储字符串,然后开启事务后让这个key自增加1(incr命令),虽然不会有报错但是语法却是不合法的,所有执行事务时这条命令会被放弃,其它的正常命令则正常执行
在事务开启前监控要监控的目标,确保目标在事务完成过程中数据的一致性,如果目标被改变了则执行事务时执行失败
悲观锁:
介绍:很悲观,无论什么时候都会枷锁
乐观锁:
介绍:很乐观认为不会出错所以不上锁,只对数据更新时做一下比较,查看是否被修改过
命令 | 功能 |
---|---|
watch key | 以乐观锁方式监控 |
unwatch | 取消所有监控 |
场景:当一个线程在进行事务操作时,如果加了监控的key被其它线程改变了数据,则执行事务时就执行失败,注:再次监控,需要先解锁
redis.conf的配置文件详解
配置 | 功能 | 例子 |
---|---|---|
计量单位不区分大小写 | 1GB 1Gb 1gb | |
【配置】 | ||
include | 导入其它配置文件 | include /path/to/loacl.conf |
pidfile | 要指定pid文件(开启守护线程才需要) | |
logfile | 日志的文件位置名 | |
【绑定】 | ||
bind | 要绑定的主机ip | bind 127.0.0.1 |
port | 指定Redis的监听端口 | port 6379 |
【模式】 | ||
protected-mode | 是否启动保护模式(外部网络是否可以直接访问) | protected-mode yes |
daemonize | 是否以守护进程运行(后台运行) | |
loglevel | 日志的模式(默认生产环境使用) | loglevel notice |
always-show-logo | 是否总是显示logo | always-show-logo yes |
stop-writes-on-bgsave-error | 持久化失败是否继续运行 | |
maxmemory-policy | 内存达到上限之后的处理策略 | maxmemory-policy noeviction |
【rdb】 | ||
rdbcompression | 是否压缩rdb文件(需要消耗一些cpu资源) | |
1rdbchecksum | 是否对rdb文件进行错误校验 | |
dir | rdb文件的保存目录 | |
【aof】 | ||
appendonly | 是否开启aop模式(默认不开启) | appendonly no |
appendfilename | 持久化文件名字 | |
appendsync | 执行什么策略的持久化 | appendsync no |
【数据库】 | ||
databases | 数据库的默认数量(默认16) | |
【快照】 | ||
save | 快照,格式:save 时间(秒) 次数 就是指定时间内,key变化次数大于次数,就进行持久化保 | save 900 1 |
【安全】 | ||
requirepass | 配置了连接密码(默认关闭) | requirepass foobared |
【限制】 | ||
maxclients | 最大客户端连接数 | |
maxmemory | Redis 最大内存限制 | |
【集群】 | ||
cluster-enabled | 是否开启集群模式,不开则是单例模式 | cluster-enabled yes |
cluster-config-file | redis集群运行时服务自身维护的配置文件 | cluster-config-file nodes.conf |
cluster-node-timeout | 集群超时时间(毫秒) | |
cluster-require-full-coverage | ||
cluster-migration-barrier | 主节点需要几个从节点,从节点才可以测试迁移 | |
cluster-announce-ip | 告诉redis实例外部映射IP | |
cluster-announce-port | 告诉redis实例外部映射端口 | |
cluster-announce-bus-port | 开启集群总线端口 |
Redis提供了将内存数据持久化到硬盘,以及用持久化文件来恢复数据库数据的功能。Redis 支持两种形式的持久化,一种是RDB快照(snapshotting),另外一种是AOF(append-only-file)
RDB:是Redis用来进行持久化的一种方式,只要满足快照的策略就把当前内存中的数据集写入磁盘(生成dump.rdb文件)
快照:策略内容就是指定时间内,key变化次数大于次数,就进行持久化保存,策略配置只需要修改redis.conf文件里的save属性即可
触发RDB方式:
数据恢复:将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可,redis就会自动加载文件数据至内存了。Redis 服务器在载入 RDB 文件期间,会一直处于阻塞状态,直到载入工作完成为止。
数据丢失:如在已经满足save 60 1000快照条件下59秒时突然宕机,数据还没有持久化就不见了,就是数据丢失
注意点:当配合aof一起使用时,重启redis只会读取aof日志文件
RDB优点:
RDB缺点:
AOF:aof持久化以日志的形式记录服务器所处理的每一个写和删除操作,但不记录查询操作,以文本的方式记录,可以打开文件看到详细的操作记录。生成的文件是appednonly.aof
AOF策略:aof持久化的记录策略,修改redis.conf里appendfsync属性实现
修复:redis通过了一个修复appednonly.aof文件的工具(redis-check-aof --fix命令),也就是说aof文件启动不了或错误时,可以通恢复进行修复
数据恢复:如果aof文件正常,启动时就会自动恢复
重写规则:如果aof文件大于指定的文件大小(默认64mb),就会就会fork新的进程来对文件进行重写(追加文件)(了解即可)
AOF优点:
AOF缺点:
redis4.x后才出现,当aof和rdb都开启时,aof触发重写条件就会对aof进行重写,而重写使用了混合持久化方法
混合持久化:先清空当前aof文件,然后对进行一次rdb然后存入到aof文件里,最后aof文件继续记录后续的写操作
触发条件:
(一)没有BGSAVE命令(RDB持久化)/AOF持久化在执行(要求)
(二)没有BGREWRITEAOF在进行(要求)
(三)AOF文件大于server.aof_rewrite_min_size
(默认为1MB)(触发机制)
(四)当前AOF文件和旧AOF文件之间大小的比率大于或等于指定比例(默认100%)(触发机制)
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。发布者发布一条信息,所有的订阅者都会接受到(如:微信公众号,关注动态等等),优秀大佬博客
命令 | 功能 |
---|---|
SUBSCRIBE 频道… | 客户端订阅任意数量的频道 |
UNSUBSCRIBE 频道… | 客户端退订任意数量的频道 |
PUBLISH 频道 消息 | 把信息发布到指定频道上 |
PSUBSCRIBE 频道… | 客户端退订指定表达式的频道 (频道=yao*,订阅所有yao开头的频道) |
PUNSUBSCRIBE 频道… | 客户端退订指定表达式的频道 (频道=yao*,订阅所有yao开头的频道) |
PUBSUB | 查看订阅与发布系统状态 |
原理结构图:
pubsub_channels
是一个字典(存储频道的字典),channel
是频道、client
是订阅者
当调用SUBSCRIBE命令时,如下粉色框新填的发布者
订阅
命令就很好理解,先在字典里遍历所有订阅频道,找到后直接把消息发给订阅者们
取消订阅
命令,先在字典里遍历所有订阅频道,在把自己从频道抹去
Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构。
简单的说,就是将一台redis服务器的数据,复制到其它服务器。前者是主节点(master/leader),后者为从节点(slave/follower);***数据的复制是单向的,只能由主节点到从节点。主节点以写为主,从节点只能读
***,这样子可以实现负载均衡
全量同步:第一次接受同步请求,在Slave初始化阶段时Slave将Master上的所有数据都复制一份的动作
增量同步:是指Slave初始化完毕后开始正常工作时主服务器发生的***写操作同步到从服务器的动作
***(写操作同步是指【主服务器】每执行一个写命令就向【从服务器】发送一个一样的命令并让其执行)
命令 | 功能 |
---|---|
info replication | 查看当前的服务器信息 |
slaveof ip port | 做指定ip的从节点(从节点) |
slaveof no one | 把自己当做主节点 |
主:命令式的主从复制是暂时性的,重启就没有了,永久性的要修改配置文件
主从复制的作用:
高可用(集群)基石
主从复制是哨兵模式和集群实施的基础
负载均衡
配合读写分离,从节点负责读,主节点负责写
故障恢复
主节点出故障,可以由从节点提供服务,实现快速修复,实际上是一种服务的冗余(因为全量复制)
哨兵模式:
没有哨兵模式前,主节点宕机了,从节点可以使用slaveof no one
命令把自己当做主节点,但主节点恢复后,从节点还认为自己是主节点(除非再次服从),简单来说就类似于谋朝篡位,这种人工干预方式费时费力,所有redis2.8后出现了Sentinel(哨兵模式)
哨兵模式出现后,如果主节点故障,哨兵1检测到这个结果并不会直接进行failover(故障转移)而是认为服务器不可用(这种现象称为主观下线),只有哨兵(其它哨兵也出现主观下线)数量达到一定值,自动的在从节点里海选(海选过程每个哨兵随机投票,票多胜出)出新的主节点并进行failover(故障转移),切换成功后通过发布订阅模式,让各个哨兵把自己监控的从服务器切换到新的主服务器(这个过程称为客观下线)
注:(1)因为哨兵也可能故障所有需要多哨兵模式相互监控 (2)如果出故障的主节点恢复了,只能当从节点
创建:
配置哨兵配置文件sentinel.conf
# port 7505 # <master-name> <ip> <port> 监控的主节点的名字、IP和端口 # <count> 设置主观下线达到多少数量,才进行客观下线
配置 | 功能 |
---|---|
port 7505 | 设置哨兵自己的端口号 |
sentinel monitor | 主节的名字(自定义)、IP和端口 设置主观下线达到多少数量,才进行客观下线 |
sentinel down-after-millseconds 30000 | 超过等待指定时长认为主节点不在线的(单位为毫秒) |
sentinel parallel-syncs 1 | 从服务器提升为主服务器后开始最多有几个从服务器过来同步数据 |
sentinel auth-pass | 配置通过添加主节点的密码 |
sentinel failover-timeout mymaster | 故障转移超时时间 |
常用命令:
命令 | 功能 |
---|---|
sentinel masters | 列出所有监视的主节点 |
sentinel slaves | 获取某主节点的所有从节点信息 |
sentinel get-master-addr-by-name | 根据主节点名称来获取其对应的ip地址 |
sentinel reset | 清除所有操作状态,包括故障转移 |
sentinel failover | 手动将主节点转移到某节点 |
缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方法:
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞
解决方法:
缓存因为断电、宕机等等导致缓存数据全部丢失引起一系列的问题就是雪崩
解决方法:
上图是redis在服务器的大致工作流程(还没用对redis进行细节规划)
使用和不使用io thread下的redis工作流程,ps:io thread是Reid4.x之后才有,需要手动开启
redis:(1)不需要手写算法、序列化 (2)redis因为只有一条工作线程的原因保证了一致性 (3)redis的类型丰富可以根据不从场景选择最佳存储方案 (4)命令和api基本一致
当存储的value较小时底层使用ziplist结构,较大时使用skiplist(下图就是skiplist结构图,ps:x是值)
然后的单机服务器都会存在两个问题,单点故障****和压力过大/性能不高**
单点故障解决方法:主从复制(也叫全量集群或主备集群)
压力/性能解决方法:分区扩容(如把原本1t的数据,分为4分扩容到其它服务器,其实也是集群的一种),再给每个分区做主从复制(否则分区出现单点故障)
区别:单点故障(数据是全量拷贝),压力/性能(部分拷贝)
** spring boot 使用参考https://blog.csdn.net/qq_27790011/article/details/98344732**