redis
redis是高级的key,value型数据库
五种数据类型
字符串string
散列hash
列表lists
集合sets
有序集合sortedsets
redis简介
redis属于NoSql,(not only sql) 不仅仅是sql 特点: 存储结构跟mysql不一样,采用的是key,value型存储 NoSql也还有很多种类: redis mongodb Hadoop Hbase
NoSql和SQL的区别
应用场景的不同;
存储方式不同;
NoSql支持关系相对简单的数据查询,不支持事务
sql支持关系相对复杂的数据查询,支持事务
redis的特性
redis是开源的,内存中的数据结构存储系统,他可以用作数据库、缓存和消息中间件 redis是由C语言编写的,支持数据持久化,是key-value型数据库 应用在缓存,消息队列中 redis支持数据备份,也就是master-slave模式
redis的优势
性能高,读取速度快,
原因:redis是完全基于内存实现的,还是单线程数据库
一般用作缓存数据库,数据放到内存中
大型项目中,一般用来存储session,购物车订单
redis的安装
1.yum安装
#前提得配置好阿里云yum源,epel源 #查看是否有redis包 yum list redis #安装redis yum install redis -y #安装好,启动redis systemctl start redis # 检查redis是否工作了 redis-cli #redis 客户端工具 #进入交互式环境后,执行ping,返回pong表示安装成功 127.0.0.1:6379> ping PONG
2.源码编译安装
# 编译安装的优势 1. 编译安装可以扩展第三方模块 2.编译安装可以统一路径,Linux软件约定安装在 /opt下 3.软件仓库版本一般比较低, 编译安装可以根据需求, 安装最新版本 1.下载redis源码 wget http://download.redis.io/releases/redis-4.0.10.tar.gz 2.解压缩 tar -zxvf redis-4.0.10.tar.gz 3.切换redis源码目录 cd redis-4.0.10.tar.gz 4.编译源文件 make 5.编译好后,src/目录下有编译好的redis指令 6.make install 安装到指定目录,默认在/usr/local/bin # 可以直接make && make install
redis的可执行文件
./redis-benchmark 用于进行redis性能测试的工具 ./redis-check-dump 用于修复出问题的dump.rdb文件 ./redis-cli redis的客户端 ./redis-server redis的服务端 ./redis-check-aof 用于修复出问题的AOF文件 ./redis-sentinel 用于集群管理
redis配置文件
redis配置文件名为 redis.conf # 这个文件可以自定义, 比如: # touch redis.s18.conf 内容如下 grep -v '^$' redis.conf |grep -v "^#" > redis.s18.conf # 去掉空格和#开头的数据写到redis.s18.conf中 # 然后 vim redis.s18.conf bind 192.168.81.132 #redis启动地址 protected-mode yes #开启redis安全模式 port 6800 #更改redis端口 daemonize yes #redis后台启动 pidfile /var/run/redis_6379.pid loglevel notice # 日志等级是notice logfile "" requirepass 666 #设置redis的密码 redis没有账号
启动、使用redis
启动redis # redis-server 指定加载的文件 # 如果redis-server 后面什么也不指定, 会以非daemon的方式来运行,且默认服务端口为6379。 redis-server redis.s18.conf 使用redis redis-cli -h 192.168.81.132 -p 6800 # 参数解释 -h 指定主机地址 -p 指定redis端口 # 登录之后通过auth指令 验证密码 如果没有密码直接ping 使用ping命令,确保redis正常可用回复了一个pong
redis简单的指令
keys * # 查看数据库所有的key type key #查看key的类型 expipe addr 20 #给addr这个key设置20秒的过期时间 ttl key #查看key的过期剩余时间 persist key # 取消key的过期时间 exists key # 判断key存在 存在返回1 否则0 del keys # 删除key 可以删除多个 dbsize # 计算key的数量 set key value # 设置key value # set name attila get key # get name 得到的是attila
redis字符串命令(string)
getrange key start end #返回key中子字符 setnx key value #只有在key不存在的时候才设置key值 setlen key #返回字符串的长度 incr key #将key中储存的数字值增一 decr key #将key中存储的数字减一 append key value #如果key存在,将value追加到老的value后面
mset key value [key1 value1......] #同时设置多个key-value对,仅限所有的key都不存在
redis哈希命令(hashs)
hdel key f1 [f2....] #删除一个或多个哈希表字段 hexists key f1 #查看字段是否存在 hget key f1 #获取指定字段值 hgetall key #获取key中所有的字段和值 hkeys key # 获取哈希表中所有的字段 hlen key #获取哈希表中字段的数量 hset key f1 value #将哈希表中key中的字段设为value
redis列表命令(list)
lindex key index #通过索引获取列表中的元素 linsert key before/after pivot value #在列表key前/后插入元素 llen key #获取列表长度 lpop key #移除并获取列表中的第一个元素 rpop key #移除列表最后一个元素,返回值为移除的元素 lrem key count value #移除列表元素 rpush key v1 [v2....] #在列表中添加一个或多个值
redis集合命令(set)
sadd key m1 [m2....] #向集合中添加一个或多个成员 scard key #获取集合中成员数 sdiff k1 [k2] #返回给定集合中的差集 sinter k1 [k2] #返回给定集合中的交集 smembers key #返回集合中所有的成员 somve s1 s2 m1 #将m1从s1集合中移动到s2集合中 spop key #随机删除并返回一个元素
redis有序集合命令(sorted set)
zadd key s1 m1 [s2 m2] #向有序集合中添加一个或多个成员,或更新成员 zcard key #获取有序集合中的成员 zcount key min max #计算指定区间的成员数 zrank key m1 #返回有序集合中成员的索引 zrem key m1 [m2] #移除有序集合中一个或多个成员
*****重头戏--->redis持久化存储
Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,
Redis提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失。
1.RDB持久化存储
RDB(持久化) 内存数据保存到磁盘 可以定期执行, 也可以手动(save)执行 RDB持久化产生的RDB文件是一个经过压缩的二进制文件,这个文件被保存在硬盘中,redis可以通过这个文件还原数据库当时的状态。 在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot) 优点:速度快,适合做备份,主从复制就是基于RDB持久化功能实现
缺点:如果持久化存储期间,redis发生故障,会发生数据丢失 rdb通过再redis中使用save命令触发 rdb
# (在redis文件下)开启rdb功能,vim redis-rdb.conf 内容如下: daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 # 这个需要mkdir -p /data/6379 dbfilename dbmp.rdb # 当触发save之后会生成dbmp.rdb这个文件 bind 127.0.0.1 save 900 1 # 每隔900秒有一个操作就执行持久化 save 300 10 save 60 10000
开启redis服务端,支持rdb功能
redis-server redis-rdb.conf
登录redis,写入数据,手动执行save出发持久化,会生成一个二进制的数据dbmp.rdb文件
redis-cli #登录redis 127.0.0.1:6379> set name attila OK 127.0.0.1:6379> save OK #退出redis,在进来, keys * name还在;如果不持久化,就没有数据
2.AOF持久化存储
AOF 文件中的命令全部以redis协议的格式保存,新命令追加到文件末尾。 优点:最大程度保证数据不丢失 缺点:日志记录非常大
# 在redis文件下 vim redis-aof.conf 写入如下数据: daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 # 也需要创建/data/6379 appendonly yes appendfsync everysec
aof持久化的两个参数
appendonly yes
appendfsync always 总是修改类的操作
everysec 每秒做一次持久化
no 依赖于系统自带的缓存大小机制
启动redis服务
redis-server redis-aof.conf
检查.data/6379文件
[root@localhost 6379]# ls appendonly.aof redis.log
登录redis,写入数据
redis-cli # 登录redis 127.0.0.1:6379> set name attila OK 127.0.0.1:6379> save OK # 最后退出redis, 重新登录redis, 输入keys * 检查结果name还在,表示持久化存储成功
实时检查appendonly.aof文件信息
# 再开一个窗口,然后检测实时动态 [root@localhost 6379]# tail -f appendonly.aof
redis在不重启的情况下,从rdb转化到aof
首先版本必须是redis2.2版本以上
# 1.启动rdb方式的redis # 2.通过命令切换为aof模式,仅仅是临时生效,切换到aof,切换后还得修改配置文件 127.0.0.1:6379> CONFIG set appendonly yes #开启AOF功能 OK 127.0.0.1:6379> CONFIG SET save "" #关闭RDB功能 OK 3.还得修改redis的配置文件,让他下次重启也是aof 修改redis-rdb.conf 为如下配置,以后重启也是aof了 daemonize yes port 6379 logfile /opt/6379/redis.log dir /opt/6379 appendonly yes appendfsync everysec # 重启redis数据库 # 4.至此redis已经切换到 aof模式下了
redis主从同步,故障切换,集群搭建
redis主从同步
准备三个配置文件,实现一主两从的redis数据库结构(这三个配置文件仅端口不同)
# redis-6379.conf 文件, 写入下面数据: port 6379 daemonize yes pidfile /data/6379/redis.pid loglevel notice logfile "/data/6379/redis.log" dbfilename dump.rdb dir /data/6379 protected-mode no
下面两个6380,6381直接替换就行
sed "s/6379/6380/g" redis-6379.conf > redis-6380.conf sed "s/6379/6381/g" redis-6379.conf > redis-6381.conf # 把6379配置成主库,6380和6381配置成从库, 需要在6380和6381的conf文件下写入: slaveof 127.0.0.1 6379
分别启动这三个redis数据库
redis-server redis-6379.conf redis-server redis-6380.conf redis-server redis-6381.conf
通过命令查看数据库的身份信息
127.0.0.1:6379> info Replication # 身份是master 127.0.0.1:6380> info Replication # 身份是slave 127.0.0.1:6381> info Replication # 身份是slave
然后测试:在主库中写入数据,在从库中查看,如果同步即为正常
redis故障切换
手动进行主从故障切换
# 演示: 1. 手动检查进程, 杀死主库. (6379) 2.手动切换到其中的一个从库(6380),去掉conf文件中的slave身份 3.切换到另一个从库(6381), 把conf文件中的slave指向改成 slaveof 127.0.0.1 6380
自动主从切换,应用哨兵机制
哨兵集群自动切换机制原理:
给数据库配置几个哨兵,让他们监控着这个数据库,隔一段时间去问一下主库,看看他是否还活着,如果主库在规定的时间内没有回复哨兵消息,哨兵就认为主库已经挂了,他会告诉其他哨兵主库挂了,其他哨兵验证之后,如果发现真的挂了,哨兵会从其他的从库中选举新的主库,然后把其他的从库slaveof执行这个新的主库。
环境配置(准备三个配置文件)
# redis-6379.conf port 6379 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" dir "/opt/redis/data/" # 另外两个如下 sed "s/6379/6380/g" redis-6379.conf > redis-6380.conf sed "s/6379/6381/g" redis-6379.conf > redis-6381.conf # 然后分别在这两个文件下写上: slaveof 127.0.0.1 6379
分别启动三个redis
redis-server redis-6379.conf redis-server redis-6380.conf redis-server redis-6381.conf
分别查看他们的身份
redis-cli -p 6379 info Replication # master 主库 redis-cli -p 6380 info Replication # slave 从库 redis-cli -p 6380 info Replication # slave 从库
准备三个哨兵,检测redis状态
# redis-26379.conf 写入下面数据: port 26379 dir /var/redis/data/ logfile "26379.log" # 当前Sentinel节点监控 127.0.0.1:6379 这个主节点 # 2代表判断主节点失败至少需要2个Sentinel节点节点同意,少数服从多数 # s18ms是主节点的别名 sentinel monitor s18ms 127.0.0.1 6379 2 # 每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒30s且没有回复,则判定不可达 sentinel down-after-milliseconds s18ms 30000 # 当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点, # 原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1 sentinel parallel-syncs s18ms 1 # 故障转移超时时间为180000毫秒 sentinel failover-timeout s18ms 180000 daemonize yes # 另外两个配置信息也只有端口不同
分别启动三个哨兵
[root@localhost s18msredis]# redis-sentinel redis-26379.conf [root@localhost s18msredis]# redis-sentinel redis-26380.conf [root@localhost s18msredis]# redis-sentinel redis-26381.conf
查看哨兵身份
[root@localhost s18msredis]# redis-cli -p 26379 info sentinel [root@localhost s18msredis]# redis-cli -p 26380 info sentinel [root@localhost s18msredis]# redis-cli -p 26381 info sentinel
测试
# 这三个哨兵检测这一主两从 1.干掉(主库)6379,查看6380和6381这两个的身份信息 2.发现其中一个从库(如:6380)变成了主库, 另一个从库变成了6380的从库 # 这个选主库是随机的. 3.当6379复活后,会自动变成6380的从库 # 原理其实就是把6380里面的slave移除啦,然后把6381的slaveof指向了6381, 6379复活后slaveof也指向了6381
redis集群搭建
redis集群搭建的原理:
其实就是对数据进行切片分摊,就好比一个一吨重的货物让一匹马去拉肯定拉不动,但是把这一吨重的货物分摊成5份,让5匹马去拉,就可以拉动了。
redis-cluster虚拟槽分区
虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。 Redis Cluster槽的范围是0 ~ 16383, 一共16384个槽位 。 槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展, 每个节点负责一定数量的槽。
准备节点(服务端)
服务端运输数据,分配16384个槽位,管理数据
ruby脚本自动帮你分配槽位
环境配置
# 创建redis-7000.conf 文件并写入如下数据: port 7000 daemonize yes dir "/opt/redis/data" logfile "7000.log" dbfilename "dump-7000.rdb" cluster-enabled yes #开启集群模式 cluster-config-file nodes-7000.conf #集群内部的配置文件 cluster-require-full-coverage no #redis cluster需要16384个slot都正常的时候才能对外提供服务, 换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 因此生产环境一般为no # 我们一共需要6个节点,也就是需要6个配置文件,3主3从,最少6个才能保证高可用,这6个配置文件仅仅是端口不同
其他几个配置文件
sed "s/7000/7001/g" redis-7000.conf > redis-7001.conf redis-7001.conf redis-7002.conf redis-7003.conf redis-7004.conf redis-7005.conf
分别启动6个redis数据库
[root@localhost s18cluster]# redis-server redis-7000.conf [root@localhost s18cluster]# redis-server redis-7001.conf [root@localhost s18cluster]# redis-server redis-7002.conf [root@localhost s18cluster]# redis-server redis-7003.conf [root@localhost s18cluster]# redis-server redis-7004.conf [root@localhost s18cluster]# redis-server redis-7005.conf
把槽分配给马车,这样马车才能运数据,ruby会自动分配
#安装准备ruby语言的环境,用于自动化创建redis集群 1.下载ruby wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz 2.解压缩 tar -zxvf ruby-2.3.1.tar.gz ./configure --prefix=/opt/ruby/ 3.安装 make && make install
配置ruby的path,就是找到ruby的bin目录的路径,然后添加到/etc/profile中的PATH中去,通过ruby的软件包管理工具安装redis模块 (gem就是类似于python的pip工具)
wget http://rubygems.org/downloads/redis-3.3.0.gem
通过gem安装这个包
gem install -l redis-3.3.0.gem
找到ruby创建redis集群脚本工具
[root@localhost s18cluster]find /opt -name redis-trib.rb
/opt/redis-4.0.10/src/redis-trib.rb
此时就可以通过绝对路径ruby来创建redis集群工具,进行槽位分配(开启所有集群)
/opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 # --replicas 1 表示每个主节点有一个从节点
查看集群状态
redis-cli -p 7000 cluster info redis-cli -p 7000 cluster nodes #等同于查看nodes-7000.conf文件节点信息 集群主节点状态 redis-cli -p 7000 cluster nodes | grep master 集群从节点状态 redis-cli -p 7000 cluster nodes | grep slave
集群已经创建完毕,开始测试
redis-cli -p 7000 -c # -c 开启集群模式 !!! 当你在其中一个节点中,创建redis的key,只要redis的key经过了重定向,分配到不同的节点中,代表集群搭建ok 重定向之后, 只要在集群里有数据 无论在哪个port里面,都可以get出来,比如set name attila 被分配到7001 你登录7000也能get到name
redis缓存击穿,缓存穿透,缓存雪崩
redis缓存穿透
redis缓存穿透:
当我们查询的时候查询一个一定不存在的对象时,redis每次请求都会去存储层去查找,这就失去了缓存的意义,当出现很多次或有人恶意发起查询的时候,数据库就挂掉了
解决方法:
采用布隆过滤器,即将所有可能存在的数据存储到一个bitmap中,一个一定不存在的数据会被这个bitmap拦截,避免对存储层的查询压力。
redis缓存击穿
缓存击穿:
当一个key在即将要过期的时间时,有大量的请求对其进行发送,这些请求发现这个key过期之后,会疯狂的从后端存储库中查找数据,此时会瞬间将DB搞崩。
解决方法:
使用互斥锁,
redis缓存雪崩
缓存雪崩:
指的是我们设置缓存时使用了相同的过期时间,导致缓存到达某一时间同时失效,请求全部到了存储库,瞬间压力过重导致雪崩。
解决方法:
将缓存失效时间分开,这样缓存失效率降低,防止过期时间一过而导致的集体失效的事件。