NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站,在某些场景下暴露出许多难以解决的问题,如性能瓶颈的问题。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。
2.1 二者区别
RDBMS(关系型数据库)
- 高度组织化结构化数据
- 结构化查询语言(SQL)
- 数据和关系都存储在单独的表中
- 数据操纵语言,数据定义语言
- 严格的一致性
- 事务遵循ACID特性(原子性、一致性、隔离性、持续性)
NoSQL
- 代表着不仅仅是SQL
- 没有声明性查询语言
- 没有预定义的模式,较为灵活
- key-value对存储,列存储,文档存储,图形数据存储
- 最终一致性,而非ACID属性
- 非结构化和不可预知的数据
- CAP定理(三进二)
- 高性能、高可用性、可拓展性
2.2 二者联系
当下关系型数据库与NoSQL二者经常是一起使用的,只不过适用的具体场景不同;针对RDBMS,比如电商网站上,商品的基本信息存放在关系型数据库中;针对NoSQL,比如一些热点高频的商品词汇可以放在Redis数据库中,因为Redis是基于内存的,拥有更高的性能;大段的文字描述则可以放在MongoDB(文档型数据库)上,因为MongoDB以BSON存储数据,适合大段文字的存储。
2.3 其他
关系型数据库常常需要多表关联查询,在分布式的情形下效率较低;而NoSQL中,很多采用冗余数据来避免关联查询。如采用BSON形式存储,每项数据都有字段名,就产生了冗余;但是一项数据基本有了该对象所有的信息,就可以避免过多的关联查询操作。
key-value对(Redis支持该类型)、文档型存储(如Mongo的BSON)、列存储(Hbase)、图关系存储(Neo4j、InfoGrid)
CAP含义:
-C(Consistency):强一致性
-A(Available):可用性
-P(Partition tolerance):分区容错性
CAP思想:一个分布式的系统不可能同时很好满足CAP三个要求,最多只能同时较好地满足其中两个特性,即三进二。
CAP的三进二:CA、AP、CP
满足CA:满足强一致性和可用性,可拓展性较弱。
满足CP:满足强一致性和分区容错性,性能不高。
满足AP:满足可用性和分区容错性,对一致性要求较低;(即不需要严格一致性而只要最终一致性)
含义:为了解决关系数据库的强一致性导致的可用性降低的问题而提出的一种解决方案。
是下面三个术语的缩写:
- 基本可用(Basically Available)
- 软状态(Soft state)
- 最终一致(Eventually consistency)
它的思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上改观,特别是分布式系统;只要满足最终一致性即可。
解决方案:统一数据服务平台:通过映射、封装等手段使各个框架有统一的接口,从而向外服务。
即远程字典服务(Remote Dictionary Server),是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,也被人们称为数据结构服务器。
关键字:KV对、基于内存、分布式、支持持久化
(1) 高性能:基于内存,所以具体较高的性能。
(2) 支持数据持久化:可用把内存的数据异步保存在磁盘中,下次重启时再次加载即可使用,从而实现了数据的持久化存储。
(3) 支持多类型数据:除了键值对,还支持list、set、zset等数据类型。
(4) 支持数据备份:采用master-slave模式进行数据备份(主从复制)
(Redis与Memcached:Memcached也是基于内存的,但不能实现数据的持久化存储,所以Memcached一般只作缓存数据库;而Redis就支持数据持久化,可以适用于更广泛的场景,如高频热门数据的长时间huan缓存,降低数据库的I/O;此外,Redis比Memcached支持更多的数据类型)
安装完成后,将安装目录下的redis.conf备份,并把conf文件下的对应行修改:daemonzize yes
这样,执行redis-server,redis的服务可以在后台运行。redis-cli则是启动客户端。
- 单进程:单进程模型来处理客户端的请求。对读写等事件的响应是通过对epoll函数的包装来做到的。Redis的实际处理速度完全依靠主进程的执行效率。
- 16个数据库:默认16个数据库,类似数组下表从零开始(0-15),初始默认使用零号库;通过select可以选择数据库。
- 数据库指令: select 数字 选择某一个数据库
dbsize 查看当前数据库的key数量
flushdb 清除当前数据库数据
flushall 清除全部数据库
常用的五大数据类型:String 、Hash、List、Set、ZSet
- String:字符串类型,是最基本的数据类型,且是二进制安全的(可以包含任何数据);一个Redis的字符串最大是512M。
- Hash:是键值对集合;value是一个String类型的field和value的映射表,适合用来存储对象。
- List:是字符串列表,底层实现是链表;链表元素的增删效率都较高。
- Set:是字符串类型的无序集合,集合内元素各不相同;通过HashTable实现。
- ZSet:字符串类型的有序集合;集合里的每一个元素都会关联一个double类型的分数,依据分数从小到大进行排序;元素一定不同,但分数可能相同。
1 //设k1为一个key,v1为一个value 2 //key常用指令的示例 3 4 keys * //查看所有存在的key 5 set k1 v1 //设置kv值,若k1已经存在则value会覆盖 6 get k1 7 exists k1 //查看键k1是否存在;存在则返回1 8 expire k1 60 //倒数60s该键失效;失效即从内存清楚 9 ttl k1 //查看还有多少秒失效;-1表示永不失效,-2表示已经失效 10 persist k1 //使永久化 11 type k1 12 move k1 2 //把k1移到2号库;原来的库就没有该键了 13 del k1
1 //String常用指令 2 3 //赋值、取值 4 set k1 abc 5 append k1 123456 //append会在k1的值后面追加一些字符 6 get k1 //结果:"abc123456" 7 8 strlen k1 //返回k1的value串的长度 9 10 //incr/decr/incrby/decrby 只能对value为数字的key才可使用 11 12 set k2 1 13 incr k2 //加1,即1+1=2 14 decr k2 //减1 15 incrby k2 N //加N;后面的数字是步长 16 decrby k2 N //减N 17 18 set k3 abcdefg 19 getrange k3 0 3 //返回0、1、2、3四个字符,即"abcd" 20 21 setrange k3 0 XXX //k3后面的offset,即偏移值;从偏移值开始,往后进行重新赋值 22 get k3 //结果"XXXdefg" 23 24 25 set k4 10 hello //设置k4 10秒后失效;注意先时间,后value 26 ttl k4 27 28 //setnx(set if not exist) 若对应的key不存在,则设置成功并返回1; 29 // 若对应的key存在, 则不设置并返回0;此指令避免覆盖 30 31 setnx k1 v1 //若k1已经存在,则返回0 32 33 34 mset k1 v1 k2 v2 k3 v3 ... //设置多个kv对 35 mget k1 k2 ... //取多个值;注意只能用空格隔开 36 37 38 msetnx k1 v1 k2 v2 ... //若这些kv都不存在,才设置成功并返回1; 39 //如果一个已经存在,则设置失败并返回0.
1 //list常用指令 2 3 //lpush 从left进行push; rpush 从right进行push; lrange 根据下标查看list 4 //对同一个list执行若干次push,会不断增加list的元素 5 6 lpush list01 1 2 3 4 5 //从左边依次push进去数字,最终在list中是1最后一位,5第一位;类比 栈 7 lrange list01 0 -1 //“先进后出” 8 /* 输出 9 1) "5" 10 2) "4" 11 3) "3" 12 4) "2" 13 5) "1" 14 */ 15 16 rpush list02 1 2 3 4 5 //从右边依次push进去数字,类比 队列 17 lrange list02 0 -1 //先进先出 18 /* 19 1) "1" 20 2) "2" 21 3) "3" 22 4) "4" 23 5) "5" 24 */ 25 26 lpop list01 //输出"5",从左边pop一个数字 27 lrange list01 0 -1 //pop一个,剩下4个 28 /* 29 1) "4" 30 2) "3" 31 3) "2" 32 4) "1" 33 */ 34 35 rpop list01 //输出"1";pop了后剩下3个 36 37 //按下标取数 Lindex 38 Lindex list01 1 //输出"3",即 4->3->2的3,下标从0开始 39 40 Llen list01 //长度为3 41 42 43 //删除N个value lrem list N value 44 rpush list03 1 2 3 4 5 6 6 6 6 45 lrem list03 3 6 //删除3个6 46 lrange list03 0 -1 47 /* 48 1) "1" 49 2) "2" 50 3) "3" 51 4) "4" 52 5) "5" 53 6) "6" 54 */ 55 56 //对非空列表的表头插入某一个元素 rpushx 右边作为表头 lpushx 左边作为表头 57 rpush list04 1 2 3 4 5 58 rpushx list04 head 59 lrange list04 0 -1 60 /* 61 1) "1" 62 2) "2" 63 3) "3" 64 4) "4" 65 5) "5" 66 6) "head" 67 */ 68 69 70 //截取原来list的一部分给原来的key 71 rpush list05 1 2 3 4 5 6 7 8 72 ltrim list05 0 3 //截取0 1 2 3 四个元素 73 lrange list05 0 -1 74 /* 75 1) "1" 76 2) "2" 77 3) "3" 78 4) "4" 79 */ 80 81 //rpoplpush 源list 目的list 从源list右端pop一个数,然后左push进目的list 82 /* 83 127.0.0.1:6379> rpush list06 1 2 3 84 (integer) 3 85 127.0.0.1:6379> rpush list07 1 2 3 86 (integer) 3 87 127.0.0.1:6379> rpoplpush list06 list07 88 "3" 89 127.0.0.1:6379> lrange list07 0 -1 90 1) "3" 91 2) "1" 92 3) "2" 93 4) "3" 94 */ 95 //list06变成2个元素,list07变成4个元素 96 97 //在指定位置前或后插入元素 98 //linsert key before/after v1 v2 在key的v1前插入v2;after可选 99 100 rpush list08 java python scala js 101 linsert list08 before python c# 102 lrange list08 0 -1 103 /* 104 1) "java" 105 2) "c#" 106 3) "python" 107 4) "scala" 108 5) "js" 109 */
1 //Set常用指令 2 3 //添加集合成员 sadd 查看集合成员 smembers 4 sadd set01 1 1 2 2 3 3 3 3 3 5 smembers set01 6 /* 7 1) "1" 8 2) "2" 9 3) "3" 10 */ 11 12 //查看成员是否属于某一个集合 sismember set member 13 sismember set01 1 //是返回1,不是返回0 14 15 //获取集合有多少个元素 16 scard set01 //返回个数 17 18 //删除集合元素 19 srem set01 1 //成功删除返回1;若不存在此元素返回0 20 21 //从集合随机出N个数 22 srandmember set N //相当于放回采样 23 24 //从集合随机pop出1个数 25 spop set //每随机pop一个数,集合set就会减少一个数;相当于不放回采样 26 27 28 //移动 29 smove key1 key2 v1[v1属于key1] //将v1由key1移动到key2; 30 //这样key1少一个元素,key2多一个元素;若v1不属于key1则返回0 31 32 //差集、交集、并集 sdiff sinter sunion 33 34 sadd set1 1 2 3 4 5 35 sadd set2 4 5 6 7 8 36 37 //差集 38 sdiff set1 set2 39 // 1) "1" 40 // 2) "2" 41 // 3) "3" 42 43 //交集 44 sinter set1 set2 45 // 1) "4" 46 // 2) "5" 47 48 //并集 49 sunion set1 set2 50 //略
1 //hash常用指令示例 2 3 //赋值与取值hset hget 4 hset user name wang 5 hget user name 6 //输出"wang" 7 8 9 //多个同时赋值、取值 10 hmset student id 1 name wang age 18 11 hmget student id name age 12 // 1) "1" 13 // 2) "wang" 14 // 3) "18" 15 16 hgetall student 17 // 1) "id" 18 // 2) "1" 19 // 3) "name" 20 // 4) "wang" 21 // 5) "age" 22 // 6) "18" 23 24 //删除 25 hdel student age //删除某一个键值对 26 27 //value中是否存在某一个key 28 hexists student id //存在返回1,不存在返回0 29 30 //查看某一个key的value中所有的key和所有的value 31 hkeys student 32 // 1) "id" 33 // 2) "name" 34 hvals student 35 // 1) "1" 36 // 2) "wang" 37 38 39 //改变哈希表中,key的value中的value 40 41 //Hincrby 只对数字有效;加参数的值;若要减则用负数 42 Hincrby student age 1 //原来18 43 /* 44 127.0.0.1:6379> Hincrby student age 1 45 (integer) 19 46 127.0.0.1:6379> Hincrby student age 1 47 (integer) 20 48 */ 49 50 //Hincrbyfloat 加浮点数的值 51 //注意,Hincrby只适用于整数的情况 52 53 54 //避免覆盖 55 hsetnx student score 99 //已经存在相应的键,则返回0;反之则设置成功。
1 //Zset常用指令示例 2 3 //普通的set key v1 v2 v3 ... 4 //有序的set key score1 v1 score2 v2 score3 v3 ... (score在前,value在后) 5 6 //添加 7 zadd zset1 3 v3 2 v2 1 v1 8 //查询 9 zrange zset1 0 -1 //从小到大排序 zrange zset1 0 -1 withscores带score 10 // 1) "v1" 11 // 2) "v2" 12 // 3) "v3" 13 14 //按照分数查询 15 zrangebyscore zset1 1 2 16 // 1) "v1" 17 // 2) "v2" 18 zrangebyscore zset1 1 (2 //加 ( 表示不包括该分数 19 // 1) "v1" 20 21 zrangebyscore zset1 1 3 limit 0 2 // limit offset count 从返回的结果中,再进行限制 22 // 1) "v1" 23 // 2) "v2" 24 25 //删除某一个值 26 zrem zset1 v3 //参数是value 27 28 //统计个数 29 zcard zset1 //返回value个数 30 zcount zset1 最小分数 最大分数 //返回分数区间内元素个数 31 32 33 //取得下标 34 zrank zset1 v1 //取得某个value的下标,从0开始 35 //取得分数 36 zscore zset1 v1 //取得某个value的分数 37 38 zrevrange zset1 0 -1 //反转;即从大到小排序 39 40 zrevrank zset1 v1 //反转后某个value的下标 41 42 zrevrangebyscore zset1 大的score 小的score //反转后按照分数取value 43
原文:https://www.cnblogs.com/dqwangi33/p/12507698.html