希望你能看完,你会对非关系型数据库有所了解,还有Redis的详细内容。
传统的MySQL中的数据都是以文件的形式存储在硬盘中的。
随着我们的互联网的持续发展,现在我们各种大型网站的访问量都非常的大,这样对数据库进行持续频繁的交互必然会影响速度,性能等。
在以往普通我们开发的网站,一般访问量都不大,所以一个数据库实例完全可以应付,但是在大型的网站中,数据量非常的大,数据库的索引也会(B+ Tree)占用内存空间。还要访问量(也就是读写混合)读写应该分开,一个实例并不能承受。
那么为了满足以上的数据库缺陷,我们必须对我们的整体架构进行进化。
随着访问量的上升,Mysql就会出现性能问题,所以我们会在Dao层跟Mysql之间加一个memcached(缓存),还有数据库的拆分,比如卖家一个数据库实例,买家一个数据库实例,也就是实现Mysql的主从读写分离。
就要分库分表操作。也就是如果有9000万条数据存放在三个库中,也算优化,不会那么慢。也就相当于形成了一个数据库的集群。
今天我们讲的Nosql就具有非常高的读写性能。它在一秒中可以写80000条数据,一秒中可以读110000万条左右的数据。
这里稍微提一下:
- 大数据时代的3V:海量(Volume)、多样(Variety)、实时(Velocity)
- 互联网需求的3高:高并发,高性能(高可用),高可扩。
OK,接下来我以阿里巴巴中文网站首页为例
在阿里巴巴中文网站首页中:
- 商品的基本信息(如名称,价格,出厂日期,生产厂商等)是存放在关系型数据库中的。
- 淘宝内部用的关系型数据库是mysql数据库,但是与普通的不一样,淘宝用的是公司大牛已改造过的数据库。(怎么能与你们这些平凡人一样呢)
- 商品的描述、详情、评价信息(多文字类)存放在文档数据库MongoDB中。
- 商品的图片存放在分布式文件系统中(淘宝自己的TFS、Google的GFS、Hadoop的HDFS)。
- 商品的关键字,搜索引擎------ISearch
- 商品的波段性的热点高频信息存放在内存数据库中(Tair、Redis、Memcache)中。
讲讲大型互联网应用(大数据、高并发、多样数据类型)的难点和解决方案
- 难点:数据类型多样性、数据源多样性和变化重构、数据源改造面数据服务平台不需要大面积重构。
- 解决方案:阿里、淘宝干了什么?UDSL(统一数据服务平台)类似于JDBC
在淘宝有一个统一数据服务层(UDSL)这个就跟JDBC一样,在网站应用集群和底层数据源之间,构建一层代理,统一数据层的特性:模型数据映射(实现业务模型各属性与底层不同类型数据源的模型数据映射),目前支持的数据库有:ISearch、Redis、MongoDB 。 统一数据服务平台:映射、API、热点缓存。
- Nosql数据存储的分类:KV键值对(Redis的kv、文档型数据库:mongoDB数据库、列存储数据库(Hadoop的Hbase)、图关系数据库(重点讲一下):它不是存放图形的,放的是关系比如:朋友圈社交网络、广告推荐系统社交网站、推荐系统等。专注于构建关系图谱)
非关系型数据库中CAP原理CAP+BASE是什么?
我们知道在传统关系型数据中是ACID(Atomicity 原子性、Consistency 一致性、Isolation 独立性、Durability 持久性)。
但是在Nosql中是CAP(Consistency 强一致性、Availability 可用性、Partition tolerance 分区容错性)
传统的数据库ACID四个性质必须都满足,但是在Nosql非关系型数据库中CAP只能3选2,因为一个分布式存储系统不可能同时很好的满足一致性、可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
那么就会出现CA、CP、AP
CA----单点集群,满足一致性,可用性的系统。
CP----满足一致性,分区容错性的系统,通常性能不是特别高。
AP----满足可用性,分区容错性的系统,通常可能对一致性要求低一些。
一般的大型公司使用的分布式存储系统都是AP。
分区容错性必须满足。
CA-----传统Oracle数据库
AP-----大多数网站架构的选择
CP-----Redis、MongoDB
BASE就是为了解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案。
BASE其实是下面三个术语的缩写:
- 基本可用(Basically Available)
- 软状态(Soft state)
- 最终一致(Eventually consistent)
它的思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上改观。为什么这么说呢?缘由就在于大型系统往往由于地域分布和极高性能的要求,不可能采用分布式事务来完成这些指标,想要获得这些指标,我们必须采用另外一种方式来完成,这里BASE就是解决这个问题的方法。
BASE就是在实现AP的基础上,弱一致性不能太离谱,比如到双十一可能点击量有1000万,但是你总不能统计出来只有100万吧,这个数据就差的太离谱了。但是最终我还是要统计出示1000万条要看,这时就采用AP+BASE的理念。
分布式系统
分布式系统由多台计算机和通信的软件组件通过计算机网络连接(本地网络或广域网)组成。分布式系统是建立在网络之上的软件系统。正式因为软件的特性,所以分布式系统具有高度的内聚性和透明性。因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。分布式系统可以引用在不同的平台上如:PC、工作站、局域网和广域网上等。
简单来说:
1. 分布式:不同的多台服务器上面部署不同的服务模块(工程),他们之间通过RPC/RMI进行之间通信和调用,对外提供服务和组内协作。
2. 集群:不同的多台服务器上面部署相同的服务模块,通过分布式调度软件进行统一的调度,对外提供服务和访问。
Redis
Redis(Remote Dictionary Server 远程字典服务器)
它是完全开源免费的,用C语言编写的,遵守BSD协议。是一个高性能的(key/value)分布式内存数据库,是基于内存运行并支持持久化的NoSQL数据库,是当前最特闷的NoSQL数据库之一,也被人们称为数据结构服务器。
为什么Redis可以取代Medcached呢?
原因有三点:
- Reids支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list、set、zset、hash等数据结构的存储
- Redis支持数据的备份,即master-slave模式的数据备份
Redis能干嘛?
内存存储和持久化,Redis支持异步将内存中的数据写到硬盘中,同时把影响继续服务取最新的N个数据的操作,如:可以将最新的条评论的ID放在Redis的List集合里面,模拟发布、订阅消息系统、定时器、计数器。
Redis是单线程的,默认是个库。
Redis里面的简单命令
keys * 显示本库中所有的数据
Flushall 全部的库的数据都删除
select 切换数据库
Dbsize 查看当前数据库的key的数量
flushdb 清空当前库的所有数据
Redis的五大数据类型
string、list、set、zset、hash(类似java里面的Map)
这里提一下:
Redis的set是string类型的无序集合,它是通过hashtable实现的。
Redis里面的zset和set一样也是string类型元素的集合,且不允许重复的成员出现,不同的是每个元素都会关联一个double类型的分数。
Reids正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但是分数(score)可以是重复的。
Redis键(key):
- keys *
- exists key名 -------- 判断某个key是否存在
- move key db名 -------- 移动key,当前库就不存在了
- ttl key --------- 查看还有多少秒过期,-1表示永不过期,-2表示已过期
- type key -------- 查看你的key是什么类型
- expire key ------ 为给定的key设置过期时间
Redis键(string):
- set/get/del/append/strlen --------不解释
- incr/decr/incrby/decrby ---------- 后面一定跟数字才能进行加减(incr k1 每次递增1, incrby k1 3 每次增加3)
- getrange/setrange --------- 相当于获取长度 (getrange k1 0 -1 表示获取所有的长度, getrange k1 0 3 表示获取4个元素)
- setex(set with expire)键秒值/setnx(set if not exist) ---- 设置过期时间 (setex k4 10 v4 设置一个k4,只能存活10s,然后消亡)
- mset/mget/msetnx -------- 一次可以获取(设置)多个(mset k1 v1 k2 v2)
- getset --------- 先get再set,先获取再设置
Redis键(list):
- lpush/rpush/lrange
- lpush表示从左边添加,rpush表示从右边添加(例如:lpush list1 1 2 3 4 5 那么我们lrange list 0 -1 查看的时候输出就是5 4 3 2 1,而rpush就是 1 2 3 4 5)
- lpop ------- 将栈顶的元素弹出
- rpop ------- 将栈底的元素弹出
- lindex ------- 按照索引下标获取元素(从上到下)
- llen --------- 查看list里面有多少个元素
- lrem key 删n个value(例:lrem list01 2 3 表示删除list01中的2个3元素)
- ltrim key index1 index2 -------- index1为开始,index2位结束,截取指定范围的值后再赋值给本key
- rpoplpush 源列表 目标列表 -------- 将源列表的栈底弹出放在目标列表的栈顶
- linsert key before/after 值1 值2
list性能总结
它是一个字符串链表,left,right都可以插入添加。如果键不存在,创建新的链表;如果键已经存在,就编程新增内容;如果值全部移除,对应的键也就消失了。链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了。
Redis键(set):
- sadd/smembers/sismember 添加元素/输出集合中的元素/输出第几个
- scard key --------- 获取集合里面的元素个数
- srem key value --------- 删除集合中的元素
- srandmember key 3 --------- 将集合中的元素 随机出3个数
- spop key ------- 随机出栈一个元素
- smove key1 key2 ---------- 在key1中的某个值赋给key2
- 数学集合类(sdiff(差集)、sinter(交集)、sunion(并集))
- sdiff set1 set2 --------- 在set1里有,但是在set2中没有的元素
Redis键(hash): 很重要!!!
kv模式不变,但V是一个键值对
- hset/hget/hmset/hmget/hgetall/hdel -------- 不解释
- hlen key -------- 查看长度
- hexists key ------- 在key里面的某个值的key
- hkeys/hvals
- hincrby/hincrbyfloat
- hsetnx
Redis键(sorted set):
在set的基础上,加一个score值。例:之前set是 k1 v1 v2 v3,现在zset是k1 score1 v1 score2 v2
- zadd/zrange ----------- 添加,获取
- zrangebyscore key 起始score 结束score ------withscore(加分数)
- zrem key --------- 某个score下对应的value值,作用是删除元素
- zcard/zcount key score区间/zrank key values值,作用是获得下标值/zscore key 对应值,获得分
- zrevrank key values值 ---------- 逆序获得下标值
Redis中的limit(限制)
Maxmemory-policy 缓存清除策略
- volatile-lru:使用LRU算法移除key,只对设置了过期的时间的键
- allkeys-lru:使用LRU算法移除key
- bolatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
- allkeys-random:移除随机的key
- volatile-ttl:移除那些ttl值最小的key,即哪些最近要过期的key
- noviction:不进行移除,针对写操作,只是返回错误信息
ok,先码到这边,下一次会详解Redis的持久化策略,感谢阅读。