NoSQL四大分类
- KV键值对:redis
- 文档型数据库(bson合适,和json一样): MongoDB,ConthDB
- 列存储数据库:HBase,分布式文件系统HDFS
- 图关系数据库:Neo4j,InfoGrid。存放的是关系,比如朋友圈社交网络关系。
Redis介绍
五种基本类型
- string
- list
- set
- hash
- zset(有序集合)
三种特殊类型
- Geospatial地理位置(存放经纬度,获取两个位置的距离)
- Hyperloglog基数统计
- Bitmap位图(全部是0和1,2的64次方数据只占12kb)
redis事务:
- 一次性 顺序性 隔离性
- 每一条指令具有原子性,但整个事务不具有原子性。
- 编译异常(一条指令出现错误,语法错误),所有的指令都不执行。
- 运行异常(语法没错,例如对一个字符串执行incre递增),当前指令执行失败,其他指令继续执行。
- 打开事务multi ,执行事务exec ,取消事务discard
- 悲观锁:认为任何时候都会出现问题,任何时候都加锁
- 乐观锁:认为任何时候都不会出问题,在更新的时候才加锁
- redis乐观锁通过watch实现,对一个值加锁,内部实现原理是更新值的时候比对这个值的version。另一线程修改了这个值,此值的version会发生变化,当前事务会执行失败,自动取消锁unwatch,后重新加锁执行事务就行
持久化存储:
-
RDB: redis database
-
设置每隔一段时间(通过redis主进程fork出来的子进程)保存一次快照dump.rdb,断电重启后redis重新加载快照文件。
优点:
1.适合大规模的数据恢复。
2.对数据的完整性要求不高。
缺点:
1.需要一定的时间间隔进行操作,一旦redis意外宕机了,最后一次快照后面操作的数据都会丢失。
2.fork子进程的时候会占用内存空间。 -
AOF: append only file
-
默认不开启,开启需要修改配置文件,把appendonly设置为yes。
-
记录每一次对redis修改的操作,追加为一个文件,名字叫appendonly.aof。
-
当文件超过64M时,会再次fork一个子进程重写一个aof文件。
-
如果aof被恶意修改出错,redis会重启不了,可以使用redis-check-aof来修复aof文件,命令是./redis-check-aof --fox appendonly.aof,自动清除掉错误的记录。
优点:
1.每一次修改都同步,文件的完整性更好。
2.默认每隔一秒同步一次,可能会丢失掉一秒的数据。
3.不开启aof的情况下效率最高。
缺点:
1.aof文件远远大于rdb文件,恢复的速度也比rdb慢。
2.aof运行效率也比rdb慢,所以默认不开启。
如果两者都开启,redis会默认从aof恢复数据,因为aof丢失的数据更少,更准确
主从复制:
- 读写分离,主节点写,从节点读。
- 主节点写的数据会自动同步到从节点。主节点挂了后,从节点不变,主节点恢复后依旧是主节点。从节点挂了后再恢复会自动同步主节点的数据。配置文件在redis.conf的replaca
哨兵模式:redis-sentinel
- sentinel monitor myredis 127.0.0.1 6379 1
- 一主二从,哨兵监测主机,主机挂了之后,哨兵会选举一个从机来作为主机。如果主机后面回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则。
优点:
1.哨兵集群,基于主从复制模式,所有的主从配置优点,它全有
2.主从可以切换,故障可以转移,系统的可用性就会更好
3.哨兵模式就是主从模式的升级,手动到自动,更加健壮
缺点:
1.redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
2.实现哨兵模式的配置其实是很麻烦的,里面有很多选择。哨兵需要有多个来配置成集群,防止一个哨兵挂了,无法工作
缓存穿透:(是查不到)
- 用户想要查询一个数据,发现redis内存缓存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败。当用户很多的时候(秒杀),缓存都没有命中,于是都去请求了持久层数据库,这就会给持久层数据库造成很大压力,这时候就相当于出现了缓存穿透。
- 解决办法:
1.布隆过滤器:BloomFilter
是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
2.缓存空对象:当存储层不命中后,即使返回空的对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据库将会从缓存中获取,保护了后端数据源。
缺点:
a.缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键。
b.即使对空值设置了过期时间,还是会存在缓存层和存储层的
c.数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
缓存击穿:(是量太大,缓存过期)
- 指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间(缓存过期),持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。一般是热点数据,微博热点服务器宕机。
- 解决方案:
- 1.设置热点数据永不过期(会导致redis缓存增大)。
- 2.加互斥锁(分布式锁):保证对于每个key同时只有一个线程去查询后端服务,这种方式将高并发的压力转移到了分布式锁,因此对分步式锁的考验很大。
缓存雪崩:
- 是指某个时间段,缓存集中过期失效。(redis宕机),比如双十一在零点之前有大量用户添加购物车,如果缓存设置1小时失效,那么在一点左右,大部分缓存会集中过期,需要重新访问数据库,对于数据库而言,就会产生周期性的压力波峰,可能造成存储层也会挂掉的情况。
- 其实集中过期倒不是非常致命,致命的是缓存雪崩,比如双十一服务器挂了。一种解决办法是,双十一的时候停掉一些服务,保证主要的服务可用(比如凌晨一点之前停掉退款服务)。
- 解决方案:
1.redis高可用
既然redis有可能挂掉,那么就多增加几台redis,就是搭建集群。(异地多活)
2.限流降级
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。停掉一些服务,保证主要服务的运行。
3.数据预热
在正式部署前,把可能的数据预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。