redis学习笔记
一、NoSQL简介
1.非关系型数据库,强调key-value,面向文档的数据库(MongoDB),不支持事务。
2.常见的NoSQL数据库
- 临时性键值存储:Redis
擅长处理数组类型的数据
具有非常快的处理速度
可以告诉处理时间序列的数据,易于处理集合运算
- 永久性键值存储:Redis
- 面向文档数据库:MangoDB
面向无需定义表结构的文档数据
具有很快的处理速度
通过BSON的形式可以保存和查询任何类型的数据
无法进行JOIN处理
二、Redis简介
1.简介
Redis:远程字典服务器,是最热门的NOSQL系统之一,数据缓存在计算机内存中,redis的数据会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,实现数据持久化。
2.特点
①redis读取速度为110000次/s 写速度为81000/s
②redis的所有操作都是原子性。
③支持多个数据结构:string、list、hash、set、zset(有序集合)
④持久化,主从复制(集群)
⑤官方版本不支持window,但是市面上有第三方版本
nosql:聚合模型:KV键值、Bson、列族、图形。
dokcer启动docker run -p 6379:6379 -d redis:latest redis-server
linux启动redis-server /myredis/redis.conf,redis-cli - p 6379
安全特性:互斥访问,即永远只有一个 client 能拿到锁.
避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况.
容错性:只要大部分 Redis 节点存活就可以正常提供服务.
数据类型:KV、set、zset、hash、list
redis支持数据的备份,master-slave模式的数据备份
redis作用:redis支持异步将内存中的数据写到硬盘,发布、订阅消息系统、定时器和计数器。
redis.conf文件:
redis默认安装完database库有16个。
redis缓存默认配置永不过期(过期策略为5种)
Volatile-lru:最近最少使用.
Volatile-random:随机移除.
Volatile-ttl:最近要过期的key.
noeviction:不进行移除,针对写操作,只返回错误信息.
redis默认不是以守护线程的方式运行,可以通过修改配置项,daemonize yes来设置。
redis日志级别:debug、verbose(默认)、notice、warning
①debug:会打印出很多信息,适用于开发和测试阶段
②verbose(冗长的):包含很多不太有用的信息,但比debug要清爽一些
③notice:适用于生产模式
④warning : 警告信息
redis持久化:rdb(Redis DataBase)、aof(Append Only File)
rdb:
①时间间隔内将内存中的数据集快照写入磁盘(Fork是复制一个与当前进程一样的进程,全新的进程,作为原进程的子进程)
②Rdb保存的是dump.rdb文件(用来下次再次使用redis时,默认从dump.rdb中读取,注意主机和备份机是两台,定时的将rdb文件复制到备机中)
③save秒钟,写操作次数:备份条件:(一分钟内改1万次,5分钟内改10次,15分钟内改1次)生成dump.rdb文件,
④如何触发快照:save(只管保存,不管其他,会产生阻塞)和bgsave(redis在后台异步进行快照操作,快照同时还可以响应客户端请求)触发
⑤如何恢复:备份文件dump.rdb移动到redis安装目录并启动服务即可
⑥优点:适合大规模数据恢复,对数据完整性和一致性要求不高
⑦缺点:在一定间隔时间做一次备份,如果redis以外停止,会损失最后一次快照的所有数据
aof:
①默认关闭的,可在appendonly.aof文件中修改为yes开启(每次做写操作会生成appendonly.aof),rdb和aof可以共存,共存时优先启用aof
②aof文件写入错误时,可用redis-checj-aof --fix appendonly.aof用来杀掉不符合规范的语法。
③aof采用文件追加方式,文件增大避免出现这种情况,新增重写机制,aof文件大小超过设置的阙值,redis启动aof文件压缩。bgrewriteaof
④aof会通过fork出一条新进程将文件重写,遍历新进程的内存中数据,每条记录有一条set语句,重写aof文件操作,并没有读取旧的aof文件。而是把整个内存中数据库内容用命令方式写了一个新aof文件。
⑤触发机制:redis记录上次重写时aof大小,默认配置当aof文件大小是上次rewrite后大小的一倍且文件大于64m触发。(.aof文件中设置,备份比例和备份大小)
两者区别:
rdb持久化方式能在指定时间间隔对数据进行快照存储。
aof持久化方式每次记录写操作,服务重启时会重新执行这些命令来恢复,aof命令每次写操作都在文件末尾追加。(如果命令太多,备份需要频繁io)
只做缓存的情况,可以不使用任何持久化方式操作,也可以同时开启两种持久化操作,优先载入aof
分布式锁:
互斥性:同一时刻,只能一个客户端持有锁。
防止死锁发生,如果吃鱼锁的客户端崩溃没有主动释放,也要保证锁可以正常释放及其他客户端可以正常加锁。
加锁和释放锁必须是同一个客户端。
容错性:只有redis还有节点存活,就可以运行正常的加锁解锁操作。
加解锁正确方式:
①命令必须保证互斥
②设置的key必须要有过期时间,防止崩溃时锁无法释放
③value使用唯一id标志每个客户端,保证只有锁的持有者才可以释放锁
加锁直接set命令同时设置唯一id和过期时间,加锁后可以返回唯一id,标志此锁是该客户端锁拥有,释放锁需要判断拥有者是不是自己,然后删除,
哨兵模式:(监控,就是自动的反客为主)
能够从后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
用法:
①在自定义的/myredis目录新建sentinel.conf文件,名字不能改
②sentinel monitor被监控数据库名字(自定义的名字)127.0.0.1 6379 1(如:sentinel monitor name6379 127.0.0.1 6379 1)谁的票数多就选谁 将从库的role:master
redis发布和订阅:
①进程间的一种消息通信模式,开发者(pub)订阅者(sub)
CAP+Base
CAP:(最多只能满足两个)
Consistency:强一致性
Availability:可用性
Partition tolerance:分区容错性
CA:单点集群,满足一致性,可用性的系统。(扩展性不强大)传统Oracle数据库
CP:满足一致性,分区容忍系统,(性能不高)大多数网站架构的选择
AP:满足可用性,分区容忍系统,(对一致性要求低)Redis、Mongodb
Base:()
基本可用:(basically Available)
软状态:(Soft state)
最终一致:(Eventually consistent)
3v+3高
海量(大量数据)、多样(多种类型数据)、实时
高并发、高可扩、高性能
redis Cluster(redis集群)
槽位:16384(用来判断数据存放在哪个存片中,客户端发送一条数据,根据槽位来判断存储在redis集群中哪个redis服务里。)
槽位计算原理:数据转换成heah值,对16384槽位取余,得出的结果来寻找redis集群中的服务,如:crc16(hello)=50018%16384=866
redis-server1的槽位区间为:0-5461
redis-server2的槽位区间为:5462-10922
redis-server3的槽位区间为:10923-16382
集群扩容机制:
linux命令,将集群中的一个或多个服务器槽位前去一些分配给新的服务器。删除的服务器不能有槽位。
缓存穿透问题解决方法
1.缓存空对象
2.布隆过滤器
缓存击穿问题:
导致原因:①从来没有访问过该数据,②缓存中没有数据库中有,这时有并发来访问该数据。
解决办法:加分布式锁
在查询库之前加上redisLock.lock(key)锁,然后再查询缓存,查询最后加上redisLock.unlock(key)解锁。
雪崩:
解决雪崩最核心的两个点:①实现高可用集群redis Cluster ②过期时间错开,避免大批数据同时失效
redis性能问题和解决方案
①Master尽量不要做持久化操作,如RDB内存快照、AOF日志文件
②如果数据比较重要,某个Slave开启AOF佩芬数据,策略设置为每秒同步一次
③为了蛀虫复制的速度和稳定性,Master和Slave最好在同一个局域网内
④尽量避免在压力很大的主库上增加从库
redis线程工作原理
I/O多路复用程序负责监听多个套接字,并向文件事件分派器传送那些产生了事件的套接字。
尽管多个文件事件可能会并发地出现, 但 I/O 多路复用程序总是会将所有产生事件的套接字都入队到一个队列里面, 然后通过这个队列, 以有序(sequentially)、同步(synchronously)、每次一个套接字的方式向文件事件分派器传送套接字。当上一个套接字产生的事件被处理完毕之后(该套接字为事件所关联的事件处理器执行完毕), I/O 多路复用程序才会继续向文件事件分派器传送下一个套接字。如果一个套接字又可读又可写的话, 那么服务器将先读套接字, 后写套接字.
Redis事务
redis事务不支持回滚,任务失败继续执行剩下的命令,所以redis的内部可以保持简单快速。
如果一个事务中的命令出现错误,那么所有的命令都不会执行
如果一个事务中出现运行错误,那么正确的命令会继续执行。
redis解决死锁
①通过redis中expire()给锁设定最大持有时间,如果超过,redis帮助释放锁。
②使用setnx key “当前系统时间+锁持有的时间”和getset key “当前系统时间+锁持有时间”组合的命令就可以实现。