网上收集整理,仅供笔记参考学习
数据库通关整理1-索引、聚簇索引、非聚簇索引、MyISAM和InnoDB存储引擎、范式
数据库通关整理2-事务、并发问题、事务隔离级别、锁(S锁、X锁`)、乐观锁、悲观锁、sql注入、内连接、外连接
数据库通关整理3-Redis基础(数据库、缓存、消息中间件)、RDB、AOF、发布订阅、主从复制、哨兵模式、缓存穿透、缓存击穿、缓存雪崩
发展历程:
1.单机MySQL
2.Memcached(缓存) + MySQL + 垂直拆分(读写分离)
3.分库拆表 + 水平拆分 + MySQL集群
4.关系型数据库不够用!数据很多,变化很快
为什么要使用NoSQL!
用户的个人信息、社交网络、地理位置。用户自己产生的数据,用户日志等等爆发式增长!
这时候我们就就需要使用NoSQL数据库,NoSQL可以很好的处理以上的情况
Redis(Remote Dictionary Server),即远程字典服务
Redis 是速度非常快的非关系型(NoSQL)数据库,可基于内存亦可持久化的日志型、Key-Value数据库。可以用作数据库
、缓存
和消息中间件MQ
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
- (数据库、缓存、消息中间件)
1、内存存储、持久化、内存中是断电即失、所以说初九话很重要(RDB、AOF)
2、效率高、可以用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器(浏览量)
6、…
特性:
1、多样的数据类型
2、持久化
3、集群
4、事务
…
1、默认是16个数据库
2、Redis是单线程的
3.为什么是单线程还这么快?
误区1:高性能的服务器一定是多线程的
误区2:多线程(CPU上下文切换)一定比单线程效率高
核心:redis是将所有数据放在内存中的,所以说使用单线程去操作效率最高。多线程(CPU上下文切换:耗时)
string 是 redis 最基本的类型,一个 key 对应一个 value。
string 类型的一个键最大能存储 512MB。
redis 127.0.0.1:6379> SET runoob “Helloworld”
OK
redis 127.0.0.1:6379> GET runoob
“Helloworld”
场景:计数器、统计多单位的数量
Map集合,key-value中的value 是一个Map
hash 是一个value键值(key=>value)对集合。
hash 是一个 string 类型的 field 和 value 的映射表.
redis 127.0.0.1:6379> HMSET runoob field1 “Hello” field2 “World”
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
redis 127.0.0.1:6379> lpush runoob redis
Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
redis 127.0.0.1:6379> sadd runoob redis
在 set 的基础上,增加一个值(分数),然后可以进行排序
关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
redis 127.0.0.1:6379> zadd runoob 0 redis
范围查询
朋友的定位,附近的人,打车距离计算
这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人
只有6个命令
什么是基数?A {1,3,3,5,7}
不重复的元素个数 = 4,可以接受误差
Hyperloglog数据结构,Hyperloglog 基数统计的算法
网页的UV(一个人访问一个网站多次,但是还是算作一个人!)
传统的方式,set保存id,统计set中数量作为标准判断。如果保存大量的id,就比较麻烦!我们的目的是计数,不是保存数据id
优点:占用内存是固定的,2^64不同的元素的技术,只需要废12kb内存,如果要从内存角度上来说,Hyperloglog是首选
0.81%错误率!统计UV任务,可以忽略不记
位存储
统计用户信息,活跃,不活跃!登录,未登录!打卡【0 1 代替】
Bitmap位图,数据结构!操作二进制位来进行记录,只有0/1两个状态
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺寻执行!
redis事务:
放弃事务:
-discard
异常:
悲观锁
redis可以实现乐观锁----watch,类似对比version版本号
解锁unwatch
乐观锁
import redis.clients.jedis.Jedis;public class RedisStringJava {public static void main(String[] args) {//连接本地的 Redis 服务Jedis jedis = new Jedis("localhost");//如果有密码,输入// jedis.auth("123456"); System.out.println("连接成功");//设置 redis 字符串数据jedis.set("runoobkey", "www.runoob");// 获取存储的数据并输出System.out.println("redis 存储的字符串为: "+ ("runoobkey"));}
}
SpringBoot操作数据:spring-data jpa mongodb redis
SpringData也是和SpringBoot齐名的项目!
lettuce
1、导入依赖
<!-- 操作redis -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、配置连接
# 配置redis
dis.host=127.0.0.1
dis.port=6379
3、测试
RedisUtils
工具类快照
300秒内,如果至少有 10 个 key 的值变化,则进行持久化操作
- save 300 10
安全
aof配置 -APPEND ONLY 模式
- appendonly no
默认是不开启aof模式的,默认是使用rdb方式持久化,在大多数情况在,rdb而完全够用- appendonly.aof 持久化的文件名字
三种配置方式:appendfsync everysec 相对常用
appendfsync always
每次修改都会sync。消耗性能appendfsync everysec
每秒执行一次sync。可能会丢失这一秒的数据!appendfsync no
不执行sync。这时候操作系统自己同步数据,速度最快具体的配置,在持久化中
…
流程
(1)redis根据配置自己尝试去生成rdb快照文件
(2)fork一个子进程出来
(3)子进程尝试将数据dump到临时的rdb快照文件中
(4)完成rdb快照文件的生成之后,就替换之前的旧的快照文件
dump.rdb,每次生成一个新的快照,都会覆盖之前的老快照
rdb保存的文件是dump.rdb,有时候在生产环境下,我们需要备份这个文件
触发机制
1、save的规则满足的情况下,会自动出发rdb规则
2、执行flushall命令,也会出发我们的rdb规则
3、退出redis,也会产生rdb文件
备份就自动生成一个dump.rdb
如何恢复rdb文件
1、只需要将rdb文件放在我们redis启动目录就可以了。redis启动的时候救护i自动检查dump.rdb恢复其中的数据!
2、查看需要存放的位置
config get dir
“dir”
“/usr/local/bin” 如果在这个目录下的dump.rdb文件没启动就会自动恢复其中的数据
流程
(1)redis fork一个子进程
(2)子进程基于当前内存中的数据,构建日志,开始往一个新的临时的AOF文件中写入日志
(3)redis主进程,接收到client新的写操作之后,在内存中写入日志,同时新的日志也继续写入旧的AOF文件
(4)子进程写完新的日志文件之后,redis主进程将内存中的新日志再次追加到新的AOF文件中
(5)用新的日志文件替换掉旧的日志文件
将我们的所有命令都记录下来,恢复的时候就把这个文件全部执行一遍
appendonly
改为yes就可以了如果aof文件有错误,redis重启时就会拒绝恢复数据
redis-check-aof --fix
命令可以修复aof文件如果文件正常,直接重启数据就恢复了
AOF重写机制
redis中的数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在redis内存中,所以可能很多之前的已经被清理掉的数据,对应的写日志还停留在AOF中,AOF日志文件就一个,会不断的膨胀,到很大很大,所以AOF会自动在后台每隔一定时间做rewrite操作,比如日志里已经存放了针对100w数据的写日志了; redis内存只剩下10万; 基于内存中当前的10万数据构建一套最新的日志,到AOF中; 覆盖之前的老日志; 确保AOF日志文件不会过大,
上一次AOF rewrite之后,是128mb。然后就会接着128mb继续写AOF的日志,如果发现增长的比例,超过了之前的100%,256mb,就可能会去触发一次rewrite但是此时还要去跟min-size,64mb去比较,256mb > 64mb,才会去触发rewrite
Redis发布订阅是一种消息通信模式:发送者发布信息,订阅者接收信息。微信、微博、关注系统!
Redis客户端可以定语任意数量的频道
订阅/发布图:
第一个:消息发送者;第二个:频道;第三个消息订阅者
数据的复制是单向的,只能由主节点到从节点。
主从复制的作用主要包括:
1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
4、高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
1)从节点执行slaveof [masterIP] [masterPort],保存主节点信息
2)从节点中的定时任务发现主节点信息,建立和主节点的socket连接
3)从节点发送Ping信号,主节点返回Pong,两边能互相通信
4)连接建立后,主节点将所有数据发送给从节点(数据同步)
5)主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来,主节点就会持续的把写命令发送给从节点, 保证主从数据一致性
复制三个redis配置文件,然后修改对应的信息
1、端口
2、pid名字
3、log
4、dump.rdb文件名
修改完毕后,启动三个redis服务器,可以通过进程信息查看
默认情况下,每台Redis服务器嗾使主节点,一般情况下配从机就可以了。
认老大!
命令配置
细节
测试:主机断开连接,从机依旧连接到主机的,但是没有写操作,此时,如果主机回来了,从机一九可以直接获取到主机写的信息!
如果是使用命令行配置的主从,如果从机重启,则默认变回主机!只要重新设置为从机,立马就可以从主机中获取到值。
复制原理
Slave启动成功连接到Master后,会发送一个sync(同步)命令
只要重新连接master,一次完全同步(全量复制)会被自动执行,数据一定可以在从机中看到!
一个接一个
谋财篡位
SLAVEOF no one
,手动让自己变为主机,其他节点就可以连接到最新的这个主节点(手动命令)主从切换技术方法:当主服务器宕机之后,需要手动把其中的一台从服务器切换成主服务器,需要人工命令干预设置,这样费时费力,还会造成一段时间内服务不可用。 这不是一种推荐的方式,更多的时候,优先考虑哨兵模式。
基础模式:
谋财篡位的自动版,可以后台监控主机是否故障,若故障就会根据票数自动将从机转换为主机。
多哨兵模式:
一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
故障切换(failover)的过程描述。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
作为一个内存数据库,redis也总是免不了有各种各样的问题
概念
用户想要查询一个数据时,发现redis内存数据库中没有,也就是缓存没有命中,于是向持久化数据库查询。发现也没有,语事本次查询失败。当用户很多时,缓存都没有命中(),语事都去请求持久数据库。 这会给持久数据库造成很大的压力,是时候就相当于缓存穿透。
解决方案
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不再对持久层查询。
将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
当首次持久存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后在访问这个数据就可以在缓存智官获取,保护了后端数据库
微博服务器宕机
集中访问缓存中的一个key
概述
key对应的数据存在,但在redis中过期失效,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
缓存击穿,是指一个key(或者某些key)非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决方案
加锁只保证只有一个进程到服务器查询,其余等待,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。
概念
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。
缓存雪崩是指,缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
在一定时间内,缓存几种过期失效,redis宕机。
比如说双十一前一个小时的抢购,快到1点时,缓存集体过期
双十一:停掉退款服务
高可用:
通过设计减少系统不能提供服务的时间。增加容错性。如:主从复制、集群
分析:
只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?
经典做法:
最经典的缓存+数据库读写的模式,就是 Cache Aside Pattern。
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候,先删除缓存,然后更新数据库。
本文发布于:2024-01-31 07:15:06,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170665650926568.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |