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种持久化机制(RDBAOF)。

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形式存储,过滤不非法查询,避免造成缓存穿透
    • 缓存空对象:设置为空对象,预先缓存!

缓存击穿

  • 高并发对一个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

  • 压力测试工具
posted @ 2022-07-31 21:54  Soul-Q  阅读(57)  评论(0编辑  收藏  举报