Redis
NoSQL 是什么?
- 泛指:非关系型数据库,随着Web 2.0 互联网时代的到来(
高并发
)传统关系型数据库
也难以应付! - 特点:
- 易扩展、大数据量——数据之间没有关系,容易扩展!
- 大数据量高性能——Redis 每秒写8万次,读11万次!
- 高可用(支持主备、集群)。
- 四大分类
- 键值存储:Redis
- 列存储 : HBase
- 文档存储:MongoDB
- 图形存储: Neo4J
为什么要用Nosql ?
-
为了解决传统数据库不能解决高并发读写、海量数据的高效率存储和访问、高可扩展性和高可用等问题。
-
网站的对数据库的操作,基本是读的操作。
-
发展过程:
- 单机年代
- 优化数据结构和索引 + 文件缓存
- Memcached(缓存)+ Mysql + 垂直拆分(读写分离)
- 分库分表 + 水平拆分(Mysql集群)
Redis是什么 ?
- 开源免费以
C语言
编写,遵守BSD协议
,支持多种数据结构、网络、数据持久化、Key-Value
的高性能数据库,以RESP
作为Redis客户端和服务端之前使用的一种通讯协议; - 执行命令是单线程,默认使用 0 号数据库,默认 16 个数据库。
- 特点:高性能,多种数据结构、原子操作、事务
应用
- 高速缓存
- 任务队列
- 发布订阅系统
- 地图信息分析
- 分布式集群架构中的session分离
- 计数器、定时器、访问统计、排行榜。
Redis 安装
#安装需要的环境
yum install gcc-c++ -y
# 检查版本
gcc -v
#上传redis
tar -zxvf redis-5.0.4.tar.gz -C /usr/local/
#去到路径下
cd /usr/local/
#重命名
mv redis-5.0.4 redis
#进入
cd redis
#编译安装
make && make install
#默认安装路径
/usr/local/bin
#执行配置
/usr/local/redis/utils/install_server.sh
修改配置、关闭保护模式、设置后台进程运行
vim /etc/redis/6379.conf
-----配置 start-----
#bind 127.0.0.1
protected-mode no
daemonize yes
-----配置 end-------
Redis Config
# 网络
bind 127.0.0.1 # 绑定的ip
protected-mode yes # 保护模式 开关
prot 6379 # 端口
# 通用
daemonize yes # 守护进程模式 开关 默认 为 no
pidfile /var/run/redis_6379.pid # 指定后台运行配置文件
loglevel notice # 日志4种级别:
# bebug -- 测试/开发阶段使用)
# verbose -- 预生产
# notice -- 生产
# warning -- 警告
logfile "" # 日志文件路径
databases 16 # 数据库数量,默认 16 个
always-show-logo yes # 启动显示Logo 开关
# 持久化
save 900 1 # 900秒内 有1个key进行修改内,进行持久化
save 300 10 # 300秒内 有10个key进行修改内,进行持久化
save 60 10000 # 60秒内 有10000个key进行修改内,进行持久化
stop-writes-on-bgsave-error yes # 持久化时出错是否继续工作 开关
rdbcompression yes # 是否对rdb文件进行压缩、需要耗费CPU资源 开关
rdbchecksum yes # 保存时校验 开关
dir ./ # 持久化文件目录
dbfilename dump.rdb # RDB 持久化文件名
# 限制
maxclients 1000 # 连接客户端的数量
maxmemory <bytes> # 最大内存容量
maxmemory-policy noeviction # 内存负荷时:6种 策略
# noeviction -- 永不过期,返回错误
# volatile-lru -- 对过期 key 进行 LRU (默认)
# allkeys-lru -- 删除 LRU 算法的 key
# volatile-random -- 随机删除过期的 key
# allkeys-random -- 随机删除
# volatile-ttl -- 删除即将过期的 key
# AOF
appendonly no # AOF 模式开关,默认开启 RDB 模式
appendfilename "appendonly.aof" # AOF 持久化的文件名
appendfsync everysec # AOF 持久化策略
# always -- 每次
# everysec -- 每秒
# no -- 不自动执行,可应用系统手动执行
no-appendfsync-on-rewrite no #
auto-aof-rewrite-percentage 100 #
auto-aof-rewrite-min-size 64mb # 设置AOF持久化文件大小,超出超出后定义新文件
Redis 数据类型
5 种 基本类型
Strings(字符串)
- 一个键最大能存储512MB。
- 应用
- 计数器
- 统计
- 对象存储
# 存
set my_soul "hello Word"
# 取
get my_soul
# 追加内容——如果不存在则Set
append my_soul "Redis"
# 获取长度
strlen my_soul
# 自增 步长为1 默认是 0
incr my_count
# 自减
decr my_count
# 设置 自增的步长
incrby my_count 10
# 设置 自减的步长
decrby my_count 5
# 截取,0 到 3
getrange my_soul 0 3
getrange my_soul 0 -1 # 返回所有
# 替换,从 1 替换
setrange my_soul 1 love
# 设置过期时间
setex my_soul 30 "Hello World!"
# 不存在则Set,常用于分布式锁
setnx my_key "MongDB"
msetnx my_key "My" my_key2 "Love" # 原子操作,要么一起成功、要么一起失败!
# 设置多个值
mset my_key1 my_value1 my_key2 my_value2 # 单机模式语法
mset {my_key}1 my_value {my_key}2 my_value21 # 集群模式语法
# 读取多个
mget my_key1 my_key2 # 单机模式语法
mget {my_key}1 {my_key}2 # 集群模式写法
# 读取修改,如果不存在则返回 nil ,如果存在,返回旧值,设置新值
getset my_db "redis"
List(列表)
- 实际是
链表
结构。 - 应用
- 消息队列
# 添加
lpush my_list one # 从左边添加
rpush my_list_r two # 从右边添加
linsert my_list before "one" "zero" # 指定某个元素前插入
linsert my_list after "two" "three" # 指定某个元素后插入
# 移除
Lpop mylist # 从左边移除
Rpop my_list_r # 从右边移除
lrem my_list 1 one # value = one 移除第一个,可以移除多个
# 读取
lrange my_list 0 -1 # 读取全部
lrange my_list 0 1 # 读取 倒数 1 和 2
lindex my_list 1 # 按下标读取
Llen my_list # 读取长度
# 截取
ltrim my_list 1 2 # 截取下标为,1 和 2 的数据
# 移动
rpoplpush my_list my_new_list # 移除最后一个元素、到一个新的列表中
# 更新
lset my_list 0 "my_redis"
Set(集合)
- 无序不重复集合!
- 应用
- 共同关注。
# 添加
sadd my_set "hello"
# 移除
srem my_set "hello" # 移除指定元素
spop my_set # 随机移除
# 查看
smembers my_set # 查看所有
sismember my_set "hello" # 判断是否存在
scard my_set # 查看集合总数
# 随机抽取
srandmember my_set 2 # 随机抽取2个
# 移动
smove my_set my_new_set "hello" # 指定元素,移到新的集合
# 交集
sinter my_set my_new_set # 两个集合的交集 应用:微博、B站:共同关注
# 并集
sunion my_set my_new_set # 两个集合的并集
# 差集,注意位置
sdiff my_set my_new_set # my_set 对于 my_new_set 的差集
sdiff my_new_set my_set # my_new_set 对于 my_set 的差集
Hash(哈希)
- Map 集合
- 应用
- 对象存储
# 添加
hset my_hash v1 "hello world"
hmset my_hash v1 "v2" v2 "v2" # 添加多个值
# 读取
hget my_hash v1
hmget my_hash v1 v2 # 读取多个值
hgetall my_hash # 读取全部
hlen my_hash # 读取长度
hexists my_hash v1 # 判断是否存在
hkeys my_hash # 获取所有的key
hvals my_hash # 获取所有的value
# 移除
hdel my_hash v1 # 删除指定key
# 增量
hset my_hash v3 5 # 设置增量步长
hincrbyf my_hash v3 1 # 加1
hsetnx my_hash v4 "Hello world" # 不存在则添加
Zset(有序集合)
- 应用
- 排行榜
# 添加
zadd my_set 1 one
# 读取
zrange my_set 0 -1
zcard my_set # 获取集合数量
zcount my_set 2 5 # 获取指定区间的数量
# 移除
zrem my_set v1
# 排序
zrangebyscore my_set -inf +inf # 正序:从负无穷到正无穷
zrangebyscore my_set -inf +inf withscores # 正序:并返回values
zrevrange my_set 0 -1 # 倒序
3 种 特殊类型
geospatial 地理位置
- 需要导入地理信息数据
geoadd china:city 121.47 31.23 shanghai
# 获取指定城市的经纬度
geopos china:city beijing
# 距离
geodist china:city beijing chongqing km
# 附近5千米
georadius china:city 110 30 500 km
hyperloglog
- 基数统计算法
- 应用
- 统计(有误差、允许有误差即可使用该算法)
# 添加
pfadd mydata a b c d e f g h
# 查看总数
pfcount mydata
#合并
pfmegre mydataResult mydata1 mydata2
bitmap
- 位存储
setbit sign 0 0
# 总数
bitcount sign
Redis 事务
- Redis 每条命令都保持原子性,但是事务不保证原子性,不存在关系型数据的隔离级别概念!
# 开启事物
multi
# 事务队列,即一组需要执行的命令
set mydata "Hello world!"
lpush myList "Your apples"
# 取消事物
discard
# 执行事务
exec
Redis 发布订阅
- Redis 发布订阅(pub/sub)是一种消息通讯模式:发送者(pub)发送消息,订阅者(sub)接收消息。
# 订阅频道
subscribe soul_blog
# 订阅多个频道
pssubscribe soul_blog
# 发布
publish soul_blog "Hello,This is Soul blog!!!!"
- 应用
- 实时消息系统
Redis 持久化
- 持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失,重启服务器之后从磁盘中恢复数据,Redis提供2种持久化机制(
RDB
、AOF
)。
RDB(Redis DataBase)
- 以时间周期进行快照保存,比
AOF
高效,适合大规模的数据且对数据完整没有要求的场景,缺点是可能会丢失最后一次持久化的数据! - 实现:创建子进程将主进程的数据复制到子进程的内存,由子进程写入临时文件中,持久化过程结束后替换上一次的快照文件,子进程退出,释放内存。
- 触发保存:
- 符合时间周期
- 执行
flushall
命令 - 停止
redis
- 恢复数据:
rdb文件
放在Redis启动目录即可,启动时会自检!
AOF(Append Only File)
- 以 日志 方式对
写
操作进行记录,恢复数据时进行有序的加载,恢复较慢,每秒同步一次,保存的数据完整性较高。
Redis 主从复制
- 主从复制 是指在Redis 集群时,
一台主机
的数据复制到多台从机
中,数据单向,由主节点到从节点。 - 主要作用:
- 数据冗余:实现数据热备份。
- 故障恢复:主节点故障时,由子节点提供服务。
- 负载均衡:实现读写分离、分担主节点的压力,提高并发能力。
- 高可用(集群):主从复制作为集群和哨兵模式的基石。
- 复制的方式
- 全量复制
- 增量复制
Redis 哨兵模式
- **哨兵 **独立的进程,可以对 Redis 主机 故障后重新投票选举新的主机。
- 实现原理是 哨兵发起命令,等待Redis响应,从而监控Redis的所有实例。——大多数
哨兵
检测到 Redis 主机故障时,由任意其一哨兵
发起投票,对 从机进行新的主机
选举,选举成功后,切换主机,通过发布订阅
模式通知其他哨兵
。
# 集群命令
redis-cli --cluster help
# 创建集群主节点(至少3个主节点,且奇数)
redis-cli --cluster create 172.18.0.21:6379 172.18.0.23:6379 172.18.0.25:6379
# 创建集群主从节点
redis-cli --cluster
create 172.18.0.21:6379
172.18.0.22:6379
172.18.0.23:6379
172.18.0.24:6379
172.18.0.25:6379
172.18.0.26:6379
--cluster-replicas 1 # 配置一台从机
# 添加主节点
redis-cli --cluster add-node 172.18.0.27:6379
# 添加从节点
redis-cli --cluster add-node 172.18.0.22:6379 172.18.0.21:6379
--cluster-slave --cluster-master-id 117457eab5071954faab5e81c3170600d5192270
# 删除节点
redis-cli --cluster del-node 172.18.0.28:6379 f6a6957421b80409106cb36be3c7ba41f3b603ff
# 查看集群信息
redis-cli --cluster info 172.18.0.22:6379
# 编写哨兵配置文件
vim sentinel.conf
#文件内容
# -----------------------配置 strar --------------------------------
# 端口
port 26379
# 后台进程运行
daemonize yes
# 哨兵的工作目录
dir /tmp
# 哨兵监控的Redis机器
sentinel monitor soulSentinel 172.18.0.21 6379 1
# Redis 服务的密码
sentinel auth-pass soulSentinel MYSUPER-secret-123456
# 哨兵 主观认为 主节点失效 默认 30 秒
sentinel down-after-milliseconds soulSentinel 300
# 故障转移的超时时间
sentinel failover-timeout soulSentinel 180000
# 通知脚本
sentinel notification-script soulSentinel /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
sentinel client-reconfig-script soulSentinel /var/redis/reconfig.sh
# -----------------------配置 end --------------------------------
#启动哨兵
./redis-sentinel sentinel.conf
# 进入哨兵
redis-cli -p 26379
# 查看哨兵状态
info sentinel
Redis 应用问题
缓存穿透
- 用户的查询没有在Redis中找到,需要向数据库频繁操作造成压力。
- 解决方案:
- 布隆过滤器:一种数据结构,对所有的查询参数以Hash形式存储,过滤不非法查询,避免造成
缓存穿透
! - 缓存空对象:设置为空对象,预先缓存!
- 布隆过滤器:一种数据结构,对所有的查询参数以Hash形式存储,过滤不非法查询,避免造成
缓存击穿
- 高并发对一个key进行访问,当key失效瞬间,请求直接访问数据库,导致数据库压力过大。
- 解决方案
- 高频的Key永不过期。
- 互斥锁:只允许一个线程访问,其他需要等待。
缓存雪崩
- Redis 服务器宕机、缓存集体失效!
- 解决方案:
- Redis 高可用。
- 限流降级:缓存失效后,控制读写的线程的操作数量。
- 数据预热:正式部署前,先缓存起来。
Redis 常用指令
# 启动Redis 服务
./redis-server /etc/redis/6379.conf
# 进入Redis
./redis-cli -p 6379
auth 01Wyl62 # 01Wyl62 为密码
# Redis 状态
service redis_6379 status
# 停止
service redis_6379 stop
# 启动
service redis_6379 start
Redis-cli 常用指令
- Redis命令文档:https://www.redis.net.cn/order/
- 注意:key定义不能过长,不能过短:一般不超过1024个字节,太长不仅容易消耗内存,而且降低查找效率,太短会降低key的可读性。
#进入Redis后检查是否可以连接Redis服务
ping
# 查看所有的key
keys *
# 查看key 是否存在
EXISTS my_soul
#移除
move my_soul
#设置过期时间
EXPIRE my_soul 10 # 设置10秒钟后过期
#查看剩余过期时间
ttl my_soul
#查看类型
type my_soul
#删除key
del my_soul
# 切换 10 号数据库
select 10
# 查看数据库大小
DBSIZE
# 监视数据
watch mydata # 可实现乐观锁
unwatch
# 停止Redis
shutdown
# 清空所有缓存
flushall
auth 01Wyl62 flushall # 01Wyl62 为密码
# 删除指定数据库内容,
select 2
flushdb
# 查看服务信息
info replication
# 集群配置,设置为从机(该机器ip:172.168.12.12)
slaveof 172.168.12.11 6379 # 172.168.12.11 为 主机
#集群信息
cluster info
#集群节点
cluster nodes
Redis-benchmark
- 压力测试工具