MongoDB&Redis基础知识
- 1. MongoDB简介
- 2. Redis
关系型数据库遵循ACID原则:
- 原子性
- 一致性
- 独立性
- 持久性
分布式系统:由多台计算机和通信的软件组件通过计算机网络连接组成,分布式系统是建立在网络之上的软件系统,因为软件的特性,所以分布式系统具有高度的内聚性和透明性。
网络和分布式系统之间的区别更多的在于高层软件而不是硬件
分布式计算的有点:
- 可靠性
- 可扩展性
- 资源共享
- 灵活性
- 高速
- 开放
- 高性能
1. MongoDB简介
由C++语言编写的,基于分布式文件存储的开源数据库系统。
在高负载时,添加更多节点,可以保证服务器的性能。
MongoDB旨在为WEB应用提供可扩展的高性能数据存储解决方案
MongoDB将数据存储为一个文档,数据结构由键值对构成,类似json对象,字段值可以包含其他文档、数组以及文档数组
特点:
- 面向文档存储的数据库
- 在MongoDB记录中设置任何属性的索引来实现更快的排序和查找
- 支持丰富的查询表达式
- map/reduce进行数据的批量处理和聚合操作
- 允许服务执行脚本(JavaScript)
- 支持各种编程语言
基础
2. Redis
全名remote dictionary server,是一个开源的使用ANSI C语言编写的,支持网络,可基于内存,可持久化的日志型,键值对数据库。
与MYSQL数据库不同的是,redis的数据存于内存中,读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存中
此外redis也经常用于做分布式锁,并支持事务、持久化、LUA脚本、LRU驱动事件、多种集群方案
五种基本数据类型:
- 字符串:使用SDS封装
使用simple dynamic string的原因:一些基础操作更加高效:获取字符串长度O(1)时间复杂度
空间预分配
惰性空间释放
二进制安全
- 哈希:哈希类型指v值本身又是一个键值对
- 列表:存储多个有序字符串
应用场景:栈、队列、有限集合、消息队列
- 集合:保存多个字符串元素,不允许重复元素
- 有序集合:已排序的字符串集合,元素不能重复
三种特殊结构:
- geospatial:地理位置定位,存储地理位置信息
- hpyerloglog:用于做基数统计算法的数据机构,如统计网站的UV
- bitmap:位图,用比特位映射元素状态
MYSQL索引为了提高效率,选择了B+树的数据结构
跳跃表是redis特有的数据结构,在链表的基础上,增加多级索引提升查找效率
合理的线程模型:
I/O多路复用:让单个线程高效的处理多个连接请求,使用epoll作为技术上的实现,redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多时间
- I/O :网络 I/O
- 多路 :多个网络连接
- 复用:复用同一个线程。
- IO多路复用其实就是一种同步IO模型,它实现了一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;而没有文件句柄就绪时,就会阻塞应用程序,交出cpu。
单线程模型
Redis是单线程模型的,而单线程避免了CPU不必要的上下文切换和竞争锁的消耗。也正因为是单线程,如果某个命令执行过长(如hgetall命令),会造成阻塞。Redis是面向快速执行场景的数据库。,所以要慎用如smembers和lrange、hgetall等命令。
Redis 6.0 引入了多线程提速,它的执行命令操作内存的仍然是个单线程。
redis自己构建了VM机制:
虚拟内存机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。通过VM功能可以实现冷热数据分离,使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。
缓存穿透: 读请求访问时,缓存和数据库都没有某个值,这样就会导致每次对这个值的查询请求都会穿透到数据库,这就是缓存穿透。
产生原因:
- 业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护。
- 业务/运维/开发失误的操作,比如缓存和数据库的数据都被误删除了。
- 黑客非法请求攻击,比如黑客故意捏造大量非法请求,以读取不存在的业务数据。
如何避免缓存穿透?
1.如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
2.如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)
3.使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。
缓存雪奔: 指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。
Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群
缓存击穿: 指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db
解决方案:
使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
“永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。