一、Nosql概述
1、单机Mysql时代
90年代,一个网站的访问量一般不会太大,单个数据库完全够用。随着用户增多,网站出现以下问题:
- 数据量增加到一定程度,单机数据库就放不下了
- 数据的索引(B+ Tree),一个机器内存也存放不下
- 访问量变大后(读写混合),一台服务器承受不住。
2、Memcached(缓存) + Mysql + 垂直拆分(读写分离)
网站80%的情况都是在读,每次都要去查询数据库的话就十分的麻烦!所以说我们希望减轻数据库的压力,我们可以使用缓存来保证效率!
优化过程经历了以下几个过程:
- 优化数据库的数据结构和索引(难度大)
- 文件缓存,通过IO流获取比每次都访问数据库效率略高,但是流量爆炸式增长时候,IO流也承受不了
- MemCache,当时最热门的技术,通过在数据库和数据库访问层之间加上一层缓存,第一次访问时查询数据库,将结果保存到缓存,后续的查询先检查缓存,若有直接拿去使用,效率显著提升。
3、分库分表 + 水平拆分 + Mysql集群
4、如今最近的年代
如今信息量井喷式增长,各种各样的数据出现(用户定位数据,图片数据等),大数据的背景下关系型数据库(RDBMS)无法满足大量数据要求。Nosql数据库就能轻松解决这些问题。目前一个基本的互联网项目:
5、为什么要用NoSQL ?
用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长!这时候我们就需要使用NoSQL数据库的,Nosql可以很好的处理以上的情况!
什么是Nosql
NoSQL = Not Only SQL(不仅仅是SQL)
Not Only Structured Query Language
关系型数据库:列+行,同一个表下数据的结构是一样的。
非关系型数据库:数据存储没有固定的格式,并且可以进行横向扩展。
NoSQL泛指非关系型数据库,随着web2.0互联网的诞生,传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区,暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的。
Nosql特点
1.方便扩展(数据之间没有关系,很好扩展!)
2.大数据量高性能(Redis一秒可以写8万次,读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)
3.数据类型是多样型的!(不需要事先设计数据库,随取随用)
4.传统的 RDBMS 和 NoSQL
传统的 RDBMS(关系型数据库)
结构化组织
SQL
数据和关系都存在单独的表中 row col
操作,数据定义语言
严格的一致性
基础的事务
...
Nosql
不仅仅是数据
没有固定的查询语言
键值对存储,列存储,文档存储,图形数据库(社交关系)
最终一致性
CAP定理和BASE
高性能,高可用,高扩展
...
5.大数据时代的3V :主要是描述问题的
海量Velume
多样Variety
实时Velocity
6.大数据时代的3高 : 主要是对程序的要求
高并发
高可扩
高性能
真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的。
二、Redis入门
Redis是什么?
Redis(Remote Dictionary Server ),即远程字典服务。
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis能干什么?
- 内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF)
- 高效率、用于高速缓冲
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(eg:浏览量)
- 。。。
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
- ...
环境搭建(略)
性能测试
redis-benchmark:Redis官方提供的性能测试工具,参数选项如下:
简单测试:
结果:
基础知识
redis默认有16个数据库
默认使用的第0个;
16个数据库为:DB 0~DB 15 默认使用DB 0 ,可以使用select n
切换到DB n,dbsize
可以查看当前数据库的大小,与key数量相关。
keys *
:查看当前数据库中所有的key。
flushdb
:清空当前数据库中的键值对。
flushall
:清空所有数据库的键值对。
Redis是单线程的,Redis是基于内存操作的。
所以Redis的性能瓶颈不是CPU,而是机器内存和网络带宽。
那么为什么Redis的速度如此快呢,性能这么高呢?QPS达到10W+
Redis为什么单线程还这么快?
核心:Redis是将所有的数据放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个CPU上的,在内存存储数据情况下,单线程就是最佳的方案。
三、五大数据类型
Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
Redis-key
在redis中无论什么数据类型,在数据库中都是以key-value形式保存,通过进行对Redis-key的操作,来完成对数据库中数据的操作。
下面学习的命令:
exists key
:判断键是否存在del key
:删除键值对move key db
:将键值对移动到指定数据库expire key second
:设置键值对的过期时间type key
:查看value的数据类型
关于TTL命令
Redis的key,通过TTL命令返回key的过期时间,一般来说有3种:
- 当前key没有设置过期时间,所以会返回-1.
- 当前key有设置过期时间,而且key已经过期,所以会返回-2.
- 当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.
关于重命名RENAME
和RENAMENX
RENAME key newkey
修改 key 的名称RENAMENX key newkey
仅当 newkey 不存在时,将 key 改名为 newkey 。
String(字符串)
普通的set、get直接略过。
常用命令及其示例:
APPEND key value
: 向指定的key的value后追加字符串
DECR/INCR key
: 将指定key的value数值进行+1/-1(仅对于数字)
INCRBY/DECRBY key n
: 按指定的步长对数值进行加减
INCRBYFLOAT key n
: 为数值加上浮点型数值
STRLEN key
: 获取key保存值的字符串长度
GETRANGE key start end
: 按起止位置获取字符串(闭区间,起止位置都取)
SETRANGE key offset value
:用指定的value 替换key中 offset开始的值
GETSET key value
: 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
SETNX key value
: 仅当key不存在时进行set
SETEX key seconds value
: set 键值对并设置过期时间
MSET key1 value1 [key2 value2..]
: 批量set键值对
MSETNX key1 value1 [key2 value2..]
: 批量设置键值对,仅当参数中所有的key都不存在时执行
MGET key1 [key2..]
: 批量获取多个key保存的值
PSETEX key milliseconds value
: 和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间
String类似的使用场景:value除了是字符串还可以是数字,用途举例:
- 计数器
- 统计多单位的数量:uid:123666:follow 0
- 粉丝数
- 对象存储缓存
List(列表)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
首先我们列表,可以经过规则定义将其变为队列、栈、双端队列等。
正如图Redis中List是可以进行双端操作的,所以命令也就分为了LXXX和RLLL两类,有时候L也表示List例如LLEN
LPUSH/RPUSH key value1[value2..]
从左边/右边向列表中PUSH值(一个或者多个)。 LRANGE key start end
获取list 起止元素==(索引从左往右 递增)== LPUSHX/RPUSHX key value
向已存在的列名中push值(一个或者多个) LINSERT key BEFORE|AFTER pivot value
在指定列表元素的前/后 插入valueLLEN key
查看列表长度LINDEX key index
通过索引获取列表元素LSET key index value
通过索引为元素设值LPOP/RPOP key
从最左边/最右边移除值 并返回RPOPLPUSH source destination
将列表的尾部(右)最后一个值弹出,并返回,然后加到另一个列表的头部LTRIM key start end
通过下标截取指定范围内的列表LREM key count value
List中是允许value重复的 count > 0:从头部开始搜索 然后删除指定的value 至多删除count个 count < 0:从尾部开始搜索… count = 0:删除列表中所有的指定value。BLPOP/BRPOP key1[key2] timout
移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。BRPOPLPUSH source destination timeout
和RPOPLPUSH功能相同,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
代码示例:
小结
-
list实际上是一个链表,before Node after , left, right 都可以插入值
-
如果key不存在,则创建新的链表
-
如果key存在,新增内容
-
如果移除了所有值,空链表,也代表不存在
-
在两边插入或者改动值,效率最高!修改中间元素,效率相对较低
应用:
消息排队!消息队列(Lpush Rpop),栈(Lpush Lpop)
Set(集合)
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
SADD key member1[member2..]
向集合中无序增加一个/多个成员 SCARD key
获取集合的成员数 SMEMBERS key
返回集合中所有的成员 SISMEMBER key member
查询member元素是否是集合的成员,结果是无序的SRANDMEMBER key [count]
随机返回集合中count个成员,count缺省值为1SPOP key [count]
随机移除并返回集合中count个成员,count缺省值为1SMOVE source destination member
将source集合的成员member移动到destination集合SREM key member1[member2..]
移除集合中一个/多个成员SDIFF key1[key2..]
返回所有集合的差集 key1- key2 - …SDIFFSTORE destination key1[key2..]
在SDIFF的基础上,将结果保存到集合中==(覆盖)==。不能保存到其他类型key噢!SINTER key1 [key2..]
返回所有集合的交集SINTERSTORE destination key1[key2..]
在SINTER的基础上,存储结果到集合中。覆盖SUNION key1 [key2..]
返回所有集合的并集SUNIONSTORE destination key1 [key2..]
在SUNION的基础上,存储结果到及和张。覆盖SSCAN KEY [MATCH pattern] [COUNT count]
在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分
代码示例
Hash(哈希)
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
Set就是一种简化的Hash,只变动key,而value使用默认值填充。可以将一个Hash表作为一个对象进行存储,表中存放对象的信息。
HSET key field value
将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0HMSET key field1 value1 [field2 value2..]
同时将多个 field-value (域-值)对设置到哈希表 key 中。HSETNX key field value
只有在字段 field 不存在时,设置哈希表字段的值。HEXISTS key field
查看哈希表 key 中,指定的字段是否存在。HGET key field value
获取存储在哈希表中指定字段的值HMGET key field1 [field2..]
获取所有给定字段的值HGETALL key
获取在哈希表key 的所有字段和值HKEYS key
获取哈希表key中所有的字段HLEN key
获取哈希表中字段的数量HVALS key
获取哈希表中所有值HDEL key field1 [field2..]
删除哈希表key中一个/多个field字段HINCRBY key field n
为哈希表 key 中的指定字段的整数值加上增量n,并返回增量后结果 一样只适用于整数型字段HINCRBYFLOAT key field n
为哈希表 key 中的指定字段的浮点数值加上增量 n。HSCAN key cursor [MATCH pattern] [COUNT count]
迭代哈希表中的键值对。
代码示例
Hash变更的数据user name age,尤其是用户信息之类的,经常变动的信息!Hash更适合于对象的存储,Sring更加适合字符串存储!
Zset(有序集合)
不同的是每个元素都会关联一个double类型的分数(score)。redis正是通过分数来为集合中的成员进行从小到大的排序。
score相同:按字典顺序排序
有序集合的成员是唯一的,但分数(score)却可以重复。
ZADD key score member1 [score2 member2]
向有序集合添加一个或多个成员,或者更新已存在成员的分数ZCARD key
获取有序集合的成员数ZCOUNT key min max
计算在有序集合中指定区间score的成员数ZINCRBY key n member
有序集合中对指定成员的分数加上增量 nZSCORE key member
返回有序集中,成员的分数值ZRANK key member
返回有序集合中指定成员的索引ZRANGE key start end
通过索引区间返回有序集合成指定区间内的成员ZRANGEBYLEX key min max
通过字典区间返回有序集合的成员ZRANGEBYSCORE key min max
通过分数返回有序集合指定区间内的成员==-inf 和 +inf分别表示最小最大值,只支持开区间()==ZLEXCOUNT key min max
在有序集合中计算指定字典区间内成员数量ZREM key member1 [member2..]
移除有序集合中一个/多个成员ZREMRANGEBYLEX key min max
移除有序集合中给定的字典区间的所有成员ZREMRANGEBYRANK key start stop
移除有序集合中给定的排名区间的所有成员ZREMRANGEBYSCORE key min max
移除有序集合中给定的分数区间的所有成员ZREVRANGE key start end
返回有序集中指定区间内的成员,通过索引,分数从高到底ZREVRANGEBYSCORRE key max min
返回有序集中指定分数区间内的成员,分数从高到低排序ZREVRANGEBYLEX key max min
返回有序集中指定字典区间内的成员,按字典顺序倒序ZREVRANK key member
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序ZINTERSTORE destination numkeys key1 [key2 ..]
计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中,numkeys:表示参与运算的集合数,将score相加作为结果的scoreZUNIONSTORE destination numkeys key1 [key2..]
计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中ZSCAN key cursor [MATCH pattern\] [COUNT count]
迭代有序集合中的元素(包括元素成员和元素分值)
代码示例
应用案例:
- set排序 存储班级成绩表 工资表排序!
- 普通消息,1.重要消息 2.带权重进行判断
- 排行榜应用实现,取Top N测试
__EOF__