文章目录
问题描述
- 问题现象
海量用户
高并发 - 罪魁祸首--------关系型数据库
- 性能瓶颈:磁盘IO性能低下
- 扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群
- 解决思路
- 降低磁盘IO次数,越低越好 ------内存存储
- 去除数据间关系,越简单越好 ---------不存储关系,仅存储数据
Nosql:即Not-only SQL(泛指非关系型的数据库),作为关系型数据库的补充。
作用: 应对基于海量用户和海量数据前提下的数据处理问题。
常见的Nosql数据库:
Redis、memcache、HBase、MongoDB
解决方案
redis概念以及特征
概念:Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库。
特征:
- 数据间没有必然的关联关系
- 内部采用单线程机制进行工作
- 高性能
- 多数据类型支持【value的类型】(字符串类型 string、列表类型 list、散列类型 hash、集合类型set、有序集合类型 sorted_set)
- 持久化支持,可以进行数据灾难恢复
redis支持的数据类型
String:
- redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性(
incr(decr) key/ incrby key increment
)
此方案适用于所有数据库,且支持数据库集群 - redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作(
setex key seconds value
) - redis应用于各种结构型和非结构型高热度数据访问加速
Hash:
存储对象信息,一个存储空间保存多个键值对数据,底层使用哈希表结构实现数据存储
- redis 应用于购物车数据存储设计
- redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计
List:
存储多个数据,并对数据进入存储空间的 顺序 进行区分,底层使用 双向链表 存储结构实现
- redis 应用于最新消息展示( 微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示)
Set:
存储大量的数据,在查询方面提供更高的效率,:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的。
- redis 应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐,大V推荐等
- redis 应用于同类信息的关联搜索,二度关联搜索,深度关联搜索(交并比)
- redis 应用于同类型数据的快速去重
- redis 应用于基于黑名单与白名单设定的服务控制
Sorted_set:
数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式,在set的存储结构基础上添加可排序字段
- redis 应用于计数器组合排序功能对应的排名
- redis 应用于定时任务执行顺序管理或任务过期管理
- redis 应用于即时任务/消息队列执行管理
redis支持的高级数据类型
Bitmaps:
redis 应用于信息状态统计
HyperLogLog:
基数是数据集去重后元素个数
HyperLogLog 是用来做基数统计的,运用了LogLog的算法
GEO:
redis 应用于地理位置计算
持久化
为了防止数据的意外丢失,确保数据安全性,利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。
RDB启动方式:
- save:手动执行一次保存操作(save指令的执行会阻塞当前Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用。)
- bgsave:手动启动后台保存操作,但不是立即执行(bgsave命令是针对save阻塞问题做的优化。Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用)
- save配置:满足限定时间范围内key的变化数量达到指定数量即进行持久化(save second changes second:监控时间范围,changes:监控key的变化量)
AOF(append only file):
以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程,解决了数据持久化的实时性,目前已经是Redis持久化的主流方式.
AOF写数据三种策略(appendfsync):always(每次 性能较低)、 everysec(每秒 性能较高)、no(系统控制)
AOF重写:
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制压缩文件体积。AOF文件重写是将Redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将对同一个数据的若干个条命令执行结果转化成最终结果数据对应的指令进行记录。
AOF重写作用:
降低磁盘占用量,提高磁盘利用率
提高持久化效率,降低持久化写时间,提高IO性能
降低数据恢复用时,提高数据恢复效率
AOF重写规则:
- 进程内已超时的数据不再写入文件
- 忽略无效指令,重写时使用进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令
- 对同一数据的多条写命令合并为一条命令
AOF重写方式:
- 手动重写(bgrewriteaof)
- 自动重写(auto-aof-rewrite-min-size size)
redis事务与锁
开启事务:multi
创建队列
执行事务:exec
取消事务:discard
监视锁: 对 key 添加监视锁,在执行exec前如果key发生了变化,终止事务执行(watch key
)
取消对所有 key 的监视(unwatch
)
分布式锁: 使用 setnx 设置一个公共锁(setnx lock-key value
)
利用setnx命令的返回值特征,有值则返回设置失败,无值则返回设置成功。对于返回设置成功的,拥有控制权,进行下一步的具体业务操作;对于返回设置失败的,不具有控制权,排队或等待。 操作完毕通过del操作释放锁。
分布式锁改良: 使用 expire 为锁key添加时间限定,到时不释放,放弃锁(expire lock-key second
)
redis 删除策略与逐出算法
删除策略
redis 是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态。
xx:具有时效性的数据
-1:永久有效的数据
-2 :已经过期的数据 或 被删除的数据 或 未定义的数据
过期数据删除策略:
-
定时删除(创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作)
优点:节约内存,到时就删除,快速释放掉不必要的内存占用
缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
总结:用处理器性能换取存储空间(拿时间换空间) -
惰性删除(数据到达过期时间,不做处理。等下次访问该数据时,如果未过期,返回数据;发现已过期,删除,返回不存在)
优点:节约CPU性能,发现必须删除的时候才删除
缺点:内存压力很大,出现长期占用内存的数据
总结:用存储空间换取处理器性能 (拿时间换空间)
每当get name的时候,会调用expireIfNeeded()查看是否过期
折中方案
3. 定期删除(周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度)
总结:周期性抽查存储空间(随机抽查,重点抽查)
逐出算法
Redis使用内存存储数据,在执行每一个命令前,会调用freeMemoryIfNeeded()
检测内存是否充足如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法。
主从复制
哨兵模式
哨兵(sentinel) 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有slave连接到新的master。哨兵也是一台redis服务器,只是不提供数据服务。通常哨兵配置数量为单数
哨兵的作用:
- 监控(不断的检查master和slave是否正常运行。master存活检测、master与slave运行情况检测)
- 通知/提醒(当被监控的服务器出现问题时,向其他(哨兵间,客户端)发送通知。)
- 自动故障转移(断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端新的服务器地址)
集群
集群就是使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果
集群作用:
分散单台服务器的访问压力,实现负载均衡
分散单台服务器的存储压力,实现可扩展性
降低单台服务器宕机带来的业务灾难
集群数据存储设计:
- 通过算法设计,计算出key应该保存的位置
- 将所有的存储空间计划切割成16384份,每台主机保存一部分,每份代表的是一个存储空间,不是一个key的保存空间
- 将key按照计算出的结果放到对应的存储空间
集群内部通讯设计:
- 各个数据库相互通信,保存各个库中槽的编号数据
- 一次命中,直接返回
- 一次未命中,告知具体位置
缓存预热:
缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
缓存雪崩:
问题:短时间范围内,大量key集中过期
缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如能够有效避免过期时间集中,可以有效解决雪崩现象的出现(约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整
缓存击穿:
问题:单个key高热数据,key过期
缓存击穿就是单个高热数据过期的瞬间,**数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,**导致对数据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与即时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可。
缓存穿透:
问题:redis中大面积出现未命中,出现非正常URL访问
缓存击穿访问了不存在的数据,跳过了合法数据的redis数据缓存阶段,每次访问数据库,导致对数据库服务器造成压力。通常此类数据的出现量是一个较低的值,当出现此类情况以毒攻毒,并及时报警。应对策略应该在临时预案防范方面多做文章。
无论是黑名单还是白名单,都是对整体系统的压力,警报解除后尽快移除。
=====================================================================================
MongoDB
MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库。BTree存储结构。不支持事务,支持索引游标等操作,优势在于查询功能比较强大,擅长查询JSON数据,能存储海量数据。
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB的最小存储单位就是文档(document)对象。文档(document)对象对应于关系型数据库的行。数据在MongoDB中以
BSON(Binary-JSON)文档的格式存储在磁盘上。