这是我参与「第五届青训营 」伴学笔记创作活动的第17天
Nosql 基本概念
为了解决高并发、高可用、高可扩展,大数据存储等一系列问题而产生的数据库解决方案,就是NoSql。
NoSql,叫非关系型数据库,它的全名Not only sql。它不能替代关系型数据库,只能作为关系型数据库的一个良好补充。
Nosql 分类:
- 键值(Key-Value)存储数据库 相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB 典型应用: 内容缓存,主要用于处理大量数据的高访问负载。 数据模型: 一系列键值对 优势: 快速查询 劣势: 存储的数据缺少结构化
- 列存储数据库 相关产品:Cassandra, HBase, Riak 典型应用:分布式的文件系统 数据模型:以列簇式存储,将同一列数据存在一起 优势:查找速度快,可扩展性强,更容易进行分布式扩展 劣势:功能相对局限
- 文档型数据库 相关产品:CouchDB、MongoDB 典型应用:Web应用(与Key-Value类似,Value是结构化的) 数据模型: 一系列键值对 优势:数据结构要求不严格 劣势: 查询性能不高,而且缺乏统一的查询语法
- 图形(Graph)数据库 相关数据库:Neo4J、InfoGrid、Infinite Graph 典型应用:社交网络 数据模型:图结构 优势:利用图结构相关算法。 劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
Redis 基本概念
Redis是使用c语言开发的一个高性能键值数据库。Redis可以通过一些键值类型来存储数据。
键值类型: String字符类型 map散列类型 list列表类型 set集合类型 sortedset有序集合类型
Redis的应用场景
缓存
合理的使用 缓存 能够明显加快访问的速度,同时降低数据源的压力。这也是 Redis 最常用的功能。Redis 提供了 键值过期时间(EXPIRE key seconds)设置,并且也提供了灵活控制 最大内存 和 内存溢出 后的 淘汰策略。
排行榜
每个网站都有自己的排行榜,例如按照 热度排名 的排行榜,发布时间 的排行榜,答题排行榜 等等。Redis 提供了 列表(list)和 有序集合(zset)数据结构,合理的使用这些数据结构,可以很方便的构建各种排行榜系统。
计数器
计数器 在网站应用中非常重要。例如:点赞数加 1,浏览数 加 1。还有常用的 限流操作,限制每个用户每秒 访问系统的次数 等等。Redis 支持 计数功能(INCR key),而且计数的 性能 也非常好,计数的同时也可以设置 超时时间,这样就可以 实现限流。
社交网络
赞/踩,粉丝,共同好友/喜好,推送,下拉刷新等是社交网站必备的功能。由于社交网站 访问量通常比较大,而且 传统的数据库 不太适合保存这类数据,Redis 提供的 数据结构 可以相对比较容易实现这些功能。
消息队列
Redis 提供的 发布订阅(PUB/SUB)和 阻塞队列 的功能,虽然和专业的消息队列比,还 不够强大,但对于一般的消息队列功能基本满足。
Redis 的主从复制
什么是主从复制
持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障,如下图:
说明:
-
主redis中的数据有两个副本(replication)即从redis1和从redis2,即使一台redis服务器宕机其它两台redis服务也可以继续提供服务。
-
主redis中的数据和从redis上的数据保持实时同步,当主redis写入数据时通过主从复制机制会复制到两个从redis服务上。
-
只有一个主redis,可以有多个从redis。
-
主从复制不会阻塞master,在同步数据时,master 可以继续处理client 请求
-
一个redis可以即是主又是从,如下图:
Redis的数据类型
string
赋值:set key value
取值: get key
取值并赋值:getset key value
设置获取多个键值: mset key value key value... mget key key...
删除 del key
应用
- 自增主键 商品编号、订单号采用 string 的递增数字特性生成
Hash
使用 string 的问题
假设有User对象以JSON序列化的形式存储到Redis中,User对象有id,username、password、age、name等属性,存储的过程如下: 保存、更新:User对象 json(string) redis
如果在业务上只是更新age属性,其他的属性并不做更新我应该怎么做呢? 如果仍然采用上边的方法在传输、处理时会造成资源浪费,下边讲的hash可以很好的解决这个问题。
介绍
hash叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。
赋值 : HSET命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0。
- 一次只设置一个字段值 语法:
hset key field value - 一次设置多个字段值 语法:
hset key field value field value…… - 当字段不存在时赋值,类似hset。区别在于如果字段存在,该命令不执行任何操作。
hsetnx key field value
取值:
- 一次获取一个字段值 语法:
hget key field - 一次可以获取多个字段值 语法:
hmget key field field... - 获取所有字段值 语法:hgetall key
删除字段:可以删除一个或多个字段,返回值是被删除的字段的个数。 语法:hdel key field [field...]
增加数字 语法:hincrby key field increment
判断字段是否存在 语法:hexists key field
只获取字段名或字段值 语法:hkeys key hvals key
获取字段数量 语法:hlen key
List 类型
ArrayList 和 LinkedList 的区别
Arraylist是使用数组来存储数据,特点:查询快、增删慢
Linkedlist是使用双向链表存储数据,特点:增删快、查询慢,但是查询链表两端的数据也很快。
Redis的list是采用来链表来存储的,所以对于redis的list数据类型的操作,是操作list的两端数据来操作的。
Set 类型
集合类型:无序、不可重复 列表类型:有序、可重复
Sortedset 类型
Sortedset 又叫 zset Sortedset 是有序集合,可排序的,但是唯一。 Sortedset 和 set 的不同之处,会给 set 中元素添加一个分数,然后通过这个分数进行排序。
常见应用问题
- 缓存穿透处理:什么是缓存穿透?当根据Redis key在缓存中查询后,不存在对应Value,就应该会在后端系统如DB中去查找,该Key的并发请求量一旦变大,那么就会对DB造成很大的压力。解决办法有:a.前端风险控制,将恶意穿透情况排除在外;b.对查询结果为空的情况依然进行缓存,但缓存时间会设置得很短,一般是几分钟。
- 缓存雪崩处理:什么是缓存雪崩?当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。解决办法有:后端连接数限制,错误阈值限制,超时处理,缓存失效时间均匀分布,前端永不失效及后端主动更新。
- 缓存时长:策略定位复杂,需要多维度的计算。
- 缓存失效:按时失效,事件失效,后端主动更新。
- 缓存Key:Hash、规则、前缀+Hash,异常情况可人工干预。
- Lua脚本:服务端批量处理及事务能力,有条件逻辑的可扩展脚本。使用它的好处有:减少网络开销、原子操作、可复用。
- Limit:可滑动时间窗口,如应用于Session,Memcached需每次传Key和Value。