基本介绍
Redis是一个NoSQL(非关系型数据库) 关系指的是表与表之间 对象与表之间的关系 非关系型数据库 存储键值
Redis优势 Redis基于内存 速度快 Redis存在数据持久化策略 Redis存在数据淘汰策略(将使用少的数据自动淘汰) Redis存在过期策略(数据到期即删除) Redis存在多个数据类型
Redis特点 基于内存,速度快,易丢失 多种数据结构 数据持久化策略 主从集群
Redis能干什么 存储token、限流、黑名单、敏感词校验、秒杀、抽奖、计数
数据类型
String
字符串
Hash
键值对
List
值可重复
Set
值不可重复
SortSet
值不可重复 排序
基本安装
1.准备文件 cp redis-5.0.7.tar.gz /usr/local 2.解压文件 tar -zxvf redis-5.0.7.tar.gz 3.安装C语言环境 yum install gcc-c++ 4.进入redis目录并编译 cd /usr/loacl/redis-5.0.7 make 5.安装redis make install 6.创建目录 mkdir -p /usr/local/redis/etc mkdir -p /usr/local/redis/bin 7.运行文件复制 cp /usr/local/redis-5.0.7/src/redis-server /usr/local/redis/bin/ cp /usr/local/redis-5.0.7/src/redis-cli /usr/local/redis/bin/ 8.redis配置文件 cp /usr/local/redis-5.0.7/redis.conf /usr/local/redis/etc/ 9.启动redis cd /usr/local/redis/bin ./redis-server /usr/local/redis/etc/ 10.设置redis为后台启动 vim /usr/local/redis/etc/redis.conf 11.重新启动 12.使用./redis-cli启动 直接进行赋值 set buliyat 111 get buliyat
基本命令
基于key
exists keyname 查看keyname是否存在 存在返回1 不存在返回0 ttl keyname 查看keyname的过期时间 expire keyname time 设置keyname的过期时间 key * 查看所有数据库中key select databaseindex 数据库切换 randomkey 随机返回key 会重复出现 redis默认存在16个数据库 0-15基于String
set key val 存储键值对 get key 通过key取出val mset k1 v1 k2 v2 存储多个键值对 mget k1 k2 通过多个key取出多个val getset key val 通过key获取val 并设置新val setnx key val 若key不存在 则存储键值对 incr key 自增 decr 自减 incrby key num 自增指定数 decrby key num 自减指定数基于hash
hset hashname key val 存储键值对 hget hashname key 通过key取出val hmset hashname k1 v1 k2 v2 存储多个键值对 hget hashname k1 k2 通过多个key取出多个val hdel hashname key 通过key删除值 hexits hashname key 判断是否存在指定key hgetall hashname 获取该集合所有键值对 hincrby hashname key num 自增指定数 hkeys hashname 获取指定集合所有key hlen hashname 查看集合键值对数量 hvals hashname 获取指定集合所有val基于list
lpush listname val 从左边向集合添加值 rpush listname val 从右边向集合添加值 lpop listname 从左侧弹出元素 rpop listname 从右侧弹出元素 brpop listname 从右侧阻塞等待输出 llen listname 查看集合中元素个数 lrange listname start end 获取范围内值基于set
sadd setname val 存储值 scard setname 查看元素个数 smember setname 获取指定集合所有val srandmember setname 随机返回指定集合val spop setname 随机弹出指定集合val sinter set1 set2 获取集合交集 sinterstore decr set1 set2 获取集合交集存储到目标集合 sunion set1 set2 获取集合并集 sunionstore decr set1 set2 获取集合并集存储到目标集合 sdiff set1 set2 获取集合差集 sdiffstore decr set1 set2 获取集合差集存储到目标集合 sismember setname val 判断元素是否存在集合中基于sortedset
zadd setname score val 存储数据 zcard setname 获取集合中的成员个数 zcount setname scores scoree 统计得分区间成员个数 zincrby setname score val 增加集合中值的得分 zrange setname indexs indexe 获取索引区间内成员 zrank setname val 返回这个val的在集合中排名 zrem setname val 删除集合中的指定val zrevrange hot:product 0 1000 返回区间的指定成员并降序排序 zrevrank hot:product 300 返回指定成员排名(降序) zscore hot:producr 100 返回指定成员得分
数据持久
数据持久化即 将内存的数据同步到硬盘上进行保存RDB模式
RDB模式 是Redis持久化策略的默认策略 RDB中存储的是二进制文件(使用二进制文件 恢复数据较快) RDB如何实现数据同步? RDB将内存数据写入硬盘前 先将硬盘中该文件内容清空 再对数据进行写入 RDB同步数据效率较低 存在数据丢失的风险 RDB在开发时几乎不使用 可用来进行数据备份(二进制存储 恢复数据快)# In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed 在900s的时间内 如果是有1个key发生改变那么变触发内存和硬盘同步 # after 300 sec (5 min) if at least 10 keys changed 在300s的时间内如果是有 10个key发生改变 那么也将触发内存和硬盘同步 # after 60 sec if at least 10000 keys changed 在60s的时间内如果是有10000个key发生改变 那么也将触发内存和硬盘同步 save 900 1 save 300 10 save 60 10000AOF模式
appendonly yes 打开AOF模式开关 aof-use-rdb-preamble no 在高版本中还需要关闭混合持久化(因为高版本中 若开启AOF 则默认打开混合持久化) RDB不需要关闭 在AOF与RDB同时存在时 AOF优先 AOF每次数据同步都是在原先基础上做追加 效率较高appendfsync always key改变 立刻同步数据 -> 数据不会丢失 -> 效率丢失 appendfsync everyec 每秒同步数据 -> 常用 -> 开发中使用 appendfsync no 不同步数据 -> 安全性能最低 -> 效率最高/redis/bin/appendonly.aof 即AOF模式文件 原语句 set buliyat 100 AOF文件的存储内容(RESP协议的协议体) *3 $3 set $5 buliyat $4 100混合持久化
混合持久化 一旦文件被重写 将RESP协议的协议体 转换为 RDB二进制 AOF大小到达64M且增长100%时 进行重写 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
淘汰策略
volatile-lru:优先淘汰存在过期时间的key 次之淘汰使用较少的key(较多使用此策略) allkeys-lfu:淘汰所有key 不管是否存在过期时间 使用较少即淘汰 allkeys-random:随机淘汰key volatile-ttl:优先淘汰剩余生存时间小的key 即优先淘汰过期时间小的key noeviction:内存满载后不再存储事务 支持读 不支持写 maxmemory-policy volatile-lru 配置缓存的淘汰策略 maxmemory <bytes> 配置Redis缓存大小
三种模式
主从模式
场景:存在一服务器最大载荷并发量为3000 现有5000并发到来 解决方案? 分离读写请求 读请求在一服务器响应 写请求在另一服务器响应 实现减压主从复制 将写入主服务器数据同步到从服务器的过程 目的是实现读写分离(主服务器用于读 从服务器用于写) 读写分离是为了减压主服务器配置 bind 0.0.0.0 daemonize yes 从服务器配置 bind 0.0.0.0 daemonize yes slaveof masterip masterport哨兵模式
场景:存在一主从模式架构 主服务器当前停止 这个问题称为单点问题 利用哨兵模式可解决此问题(可存在多个哨兵)哨兵模式可解决主从模式下出现的单点问题 在主服务器停止后 哨兵开始在所剩从服务器中进行选举 从服务器获胜成为新主服务器 哨兵是一个独立的程序 可以部署到任意机器配置 num为选举时通过机票可成为主服务器 默认为1 即先获得1票的从服务器成为主服务器 sentinel monitor mymaster masterip masterport num 启动redis哨兵 ./redis-server /usr/local/redis/etc/sentinel.conf --sentinel &集群模式
哨兵模式保证了主服务器的存在 但当并发较大时 一个主服务器并不能满足需求 所以需要多主多从 即集群模式 横向上搭建集群 扩容 纵向上搭建集群 减压1.创建文件夹 mkdir /usr/local/redis-cluster/1001 ... mkdir /usr/local/redis-cluster/1006 2.拷贝配置文件 cp /usr/local/redis-5.0.7/redis.conf /usr/local/redis-cluster/1007 3.修改配置文件 bind 0.0.0.0 port 1001 daemonize yes pidfile /var/run/redis_1001.pid dir "/usr/local/redis-cluster/7001" appendonly yes cluster-enabled yes cluster-config nodes-1001.config 4.依次拷贝至1002...1006 5.修改配置文件(1001改为100x对应) 1001->100x 6.启动服务器 ./redis-server /usr/local/redis-cluster/1001/redis.conf ... ./redis-server /usr/local/redis-cluster/1007/redis.conf 7.创建集群 redis-cli --cluster create 127.0.0.1:1001 127.0.0.1:1002 127.0.0.1:1003 127.0.0.1:1004 127.0.0.1:1005 127.0.0.1:1006 --cluster-replicas 1 8.登录服务器 测试 ./redis-cluster -c -h 192.168.108.137 -p 1001
常见问题
缓存穿透
大量请求key是不合理的 既不存在于缓存也不存在于数据库 导致请求到达数据库 对数据库造成巨大压力 从而崩溃 解决方案 缓存无效key:若redis与数据库都不存在某个key的数据 则写一个key到redis并设置过期时间 布隆过滤器:能够很方便地判断给定数据是否存在于大量数据中 把所有可能存在的请求值存放到布隆过滤器 请求经由布隆过滤器后判断是否存在 不存在则返回错误信息 存在则进行数据查询缓存击穿
请求key为热点数据 在进入redis时该数据过期 再去找数据库 导致大量请求到达数据库 从而崩溃 解决方案 热点数据设置永久不过期或过期时间较长 请求数据库时 获取互斥锁 保证只有一个请求到达数据库 减少数据库压力缓存雪崩
redis中的key在同一时间大量过期 导致请求到达数据库 对数据库造成巨大压力 从而崩溃 解决方案 采用redis集群 避免单机出现问题而导致整个缓存服务无法使用 限流 避免同时处理大量请求脑裂效应
reids当前主服务器出现暂时"失联" 导致哨兵误以为主服务器死亡而开始选举 产生新主服务器 此时旧主服务器恢复 开始处理请求 但此时存在两个主服务器 导致从服务器混乱 即脑裂效应 数据丢失:不同客户端可能会向不同主节点写入数据 当进行数据同步时 可能会产生数据丢失的情况 解决方案: 配置最小从服务器数:min-slaves-to-write 存在至少N个正常从服务器才执行写命令 配置从连接最大延迟时间:min-slaves-max-log 主从数据库进行数据复制ACK消息延迟的最大时间