一、NoSQL简介
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库。
NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入,NoSQL的非关系特性助力大型Web2.0网站的再次起飞,使其成为了后Web2.0时代的宠儿。
单机时代模型
如果每次存储成千上万条数据,这样很会导致mysql的性能很差,存储以及读取速度很慢,然后就演变成缓存+mysql+垂直拆分的方式。
Cache作为中间缓存
将所有的数据先保存到缓存中,然后再存入mysql中,减小数据库压力,提高效率。
但是当数据再次增加到又一个量级,上面的方式也不能满足需求,由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可扩展性。Mysql的master-slave模式成为这个时候的网站标配了。
主从分离模式
在redis的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM。
分表分库模式
将变化小的、业务相关的放在一个数据库,变化多的,不相关的数据放在一个数据库。
二、NoSQL的风声水起
随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题:
1. 对数据库高并发读写的需求
网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。
2. 对海量数据的高效率存储和访问的需求
对于大型的SNS网站,每天用户产生海量的用户动态,以国外的Friendfeed为例,一个月就达到了2.5亿条用户动态,对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。
3. 对数据库的高可扩展性和高可用性的需求
在基于Web的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像Web服务器和应用服务器那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供7*24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,为什么数据库不能通过不断的添加服务器节点来实现扩展呢?
在上面提到的“三高”的需求面前,关系数据库遇到了难以克服的障碍,而对于Web2.0网站来说,关系数据库的很多主要特性却往往无用武之地,例如:
1. 数据库事务一致性需求
很多Web实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一致性要求也不高。因此数据库事务管理成了数据库高负载下一个沉重的负担。
2. 数据库的写实时性和读实时性需求
对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的。并不要求这么高的实时性。
3. 对复杂的SQL查询,特别是多表关联查询的需求
任何大数据量的Web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询,特别是SNS类型的网站,从需求以及产品设计角度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能被极大的弱化了。
而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
三、NoSQL无与伦比的特点
在大数据存取上具备关系型数据库无法比拟的性能优势,例如:
1. 易扩展
NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。
2. 大数据量,高性能
NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。
3. 多样灵活的数据模型
在NoSQL中不仅可以存储String,hash,set、Zset等数据类型,还可以保存javaBean以及多种复杂的数据类型。NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的Web2.0时代尤其明显。
4. 高可用
NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。比如Cassandra,HBase模型,通过复制模型也能实现高可用。
四、Redis的脱颖而出
1、redis简介
redis是NoSQL数据库中使用较为广泛的非关系型内存数据库,redis内部是一个key-value存储系统。它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型,类似于Java中的map)。Redis基于内存运行并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,也被人们称为数据结构服务器。
2、redis特点
- 速度快
Redis是用C语言实现的;
Redis的所有数据存储在内存中。 - 持久化
Redis的所有数据存储在内存中,对数据的更新将异步地保存到磁盘上。 - 支持多种数据结构
Redis支持五种数据结构:String、List、Set、Hash、Zset - 支持多种编程语言
Java、php、Python、Ruby、Lua、Node.js - 功能丰富
除了支持五种数据结构之外,还支持事务、流水线、发布/订阅、消息队列等功能。 - 源码简单
约23000行C语言源代码。 - 主从复制
主服务器(master)执行添加、修改、删除,从服务器执行查询。 - 高可用及分布式
Redis-Sentinel(v2.8)支持高可用
Redis-Cluster(v3.0)支持分布式
和Memcached类似,Redis支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。与Memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步(数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。)。
因此,Redis的出现,很大程度补偿了Memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。
3、如何使用redis?
你一定要知道的是:redis的key名要区分大小写,在redis中除了 和空格外,其他的字符都可以做为key名,且长度不做限制,不过为了性能考虑,一般key名不要设置的太长。redis功能强大,支持数据类型丰富,以下是redis操作命令大全,基本上涵盖了redis所有的命令!
1、redis命令基本篇
- 【 set key value 】 存入一个key和值。如:set myname reson
- 【 get key 】 读取一个key的值。
- 【 del key 】 删除一个key。
- 【 del key1 key2 ... keyN 】 删除多个key。如:del myname1 myname2
- 【 exists key 】 判断一个key是否存在。
- 【 type key 】 查看key的类型。
- 【 rename key keyNew 】 重命名key名。如:rename myname myname2
- 【 dbsize 】 查看当前库中的key的条数。
- 【 expire key time 】 指定key的过期时间,单位为秒。如:expire myname 9(设置9秒后过期)
- 【 ttl key 】 查看redis有多长时间过期,单位为秒。
- 【 keys * 】 列出当前库中所有的key名。
- 【 keys a* 】 列出当前库中所有以字符串“a"开头的key。
- 【 select db-index 】 选择一个数据库,如选择第一个数据库:select 0;选择第二个 select 1;默认有16个数据库,这个值可以在redis.conf中配置。
- 【 flushdb 】 清掉当前库中所有的key(生产环境下需谨慎操作)。
- 【 flushall 】 清掉所有库中全部的key(生产环境下需谨慎操作)。
- 【 mset key1 value1 key2 value2 ... keyN valueN 】 一次性存入多个key和值。
- 【 mget key1 key2 ... keyN 】 一次性读取多个key。
- 【 incr key 】 可以对key类型+1的操作(相当于编程语言里面的++),只能操作number型,操作字符串会报错。可对新值进行操作。
- 【 decr key 】 可以对key类型-1的操作(相当于编程语言里面的--),只能操作number型,操作字符串会报错。
- 【 incrby key num 】 同incr,对key的值加num,比如 incrby aa 10,对aa+10。
- 【 decrby key num 】 同上,对key的值减num。
- 【 append key value 】 对指定key的字符串进行追加,如果key为整形,会被转为字符串。如aa的值为9,执行append aa 10后,会变成910。
- 【 substr key start end 】 对key进行截取start到end个字符。如aa的值为:abcdef,执行substr aa 2 3后,返回“cd”。
2、redis链表类型(list)命令
- 【 lpush key value 】 往队列头部插入一个元素
- 【 rpush key value 】 从尾部插入一个元素
- 【 lpop key 】 从队列头部删掉一个元素
- 【 rpop key 】 从队列尾部删掉一个元素,并返回被删除元素的值
- 【 llen 】 返回队列的长度,即里面有多少个元素。不存在key返回0,不为队列类型的key会返回报错。
- 【 lrange key start end 】 返回队列从start到end之间的元素信息。
- 【 ltrim key start end 】 截取一个队列,只保留指定区间内的元素。
3、redis无序集合set类型命令
- 【 sadd key vaule 】 往集合中插入一个元素,如果value值已存在集合中,则返回0,不会被重复插入。
- 【 sinter key1 key2 ... keyN 】 取出n个key之间的交集。比如 key1里面有值a,b,c,d,e,key2里面有d,e,f,sinter key1 key2返回d,e。
- 【 sunion key1 key2 ... keyN 】 取出n个key之间的并集。比如 key1里面有值a,b,c,d,e,key2里面有d,e,f,sunion key1 key2返回a,b,c,d,e,f。
- 【 sdiff key1 key2 】 取出n个key之间的差集。比如 key1里面有值a,b,c,d,e,key2里面有d,e,f,sdiff key1 key2返回a,b,c;反过来sdiff key2 key1返回f。
- 【 smembers key 】 返回key集合中所有的元素,结果是无序的。
- 【 sismember key value 】 查看value这个值是否在key集合中。存在返回1,不存在返回0。
- 【 scard key 】 返回集合中有多少个元素。
- 【 smove key1 key2 value 】 把value从key1中移到key2中去。
- 【 srem key value1 value2 ... valueN 】 从key集合中删掉某些元素。
4、redis有序集合sorted set命令
- 【 zadd key v k 】 往key中添加一个元素,k为键,v为值。如:zadd artHits 99 12表示id为12的文章点击量为99次。
- 【 zrange key start end 】 根据v的值由小到大进行排序来获得start到end之间的元素。
注:0表示第一个元素,-1表示最后一个元素,-2表示倒数第二个元素,以此类推,如果要获取第一个到倒数第三个之间的元素,命令为:zrange key 0 -3。 - 【 zrevrange key start end 】 同上,根据v的值由大到小进行排序来获得start到end之间的元素。可以轻松取出点击量最高的前n篇文章。
- 【 zremrangebyrank key start end 】 删除集合中的元素。排序的方式为按照v由小到大的顺序,如果要删除key集合中的第一个值,则运行 zremrangebyrank artHits 0 0;删除前3个值:zremrangebyrank artHits 0 2。
- 【 zcard 】 返回key集合中元素的个数。
- 【 zrank key k 】 返回值k在集合key中排第几位,是按照v由小到大的顺序。排第一名返回0,第二返回1,以此类推。
- 【 zrevrank key k 】 同上,不同的是,按照v由大到小的顺序。可以轻松取出点击量最高的文章。
- 【 zscore key k 】 取出集合key中键为k对应的值v。
- 【 zrem key k 】 删除集合中指定元素。
- 【 zincrby key num k 】 给集合key中的元素k加上num,值针对整型。比如 zincrby artHits 3 12,给id为12的文章加上3个点击量。此时zscore artHits 12的结果是99+3为102。
5、redis哈希hash类型命令
- 【 hset key field value 】 设置hash field为指定值,如果key不存在,则先创建。
- 【 hmset key field1 value1 ... fieldN valueN 】 同时设置多个值。
- 【 hget key field 】 获取指定的hash field
- 【 hmget key field1 field1 ... fieldN 】 获取指定的多个hash field
- 【 hincrby key field num 】 将指定的hash field加上指定的值。
- 【 hexists key field 】 查看指定field是否存在。
- 【 hdel key field 】 删除指定的hash field。
- 【 hlen key 】 返回指定hash中field的数量。
- 【 hkeys key 】 返回hash所有的field。
- 【 hvals 】 返回hash中所有的value。
- 【 hgetall key 】 返回hash中所有的field和value。