目录
1.2.Memcached(缓存)+Mysql+垂直拆分(读写分离+缓存)
1.先聊Nosql概述
为什么要用Nosql,不用mysql呢?
1.1.单机mysql的时代
90年代,一个基本的网站访问量一般不会太大,单个数据库完全足够,那个时候基本都是静态网页,服务端无压力。大数据时代的当下,网站的瓶颈是什么?
- 数据量太大,一个msql放不下
- 数据量太大,数据库索引(B+ Tree),一个服务器内存也放不下
- 访问量读写混合,一个服务器也承受不了
1.2.Memcached(缓存)+Mysql+垂直拆分(读写分离+缓存)
网站80%的情况都是读,每次都去查询数据库就十分麻烦,为了减轻数据库压力,可以使用缓存来保证效率
一个数据库去写,很多的数据库去读,读写分离+缓存,发展过程:优化数据库结构和索引->I/O->缓存
也可以说是主从复制:主去写,从去读
1.3.分库分表+水平拆分+mysql集群
本质:数据库(读,写)
早些年mysql引擎是MyISAM:表锁,十分影响效率!高并发下就是灾难
所以出现了新的引擎Innodb:行锁
慢慢的就开始使用分库分表来解决写的压力,Mysql在那个年代就推出了表分区和Mysql集群
1.4.如今最近的年代
大数据的到来,Mysql等关系数据库都不够用了数据量很多,变化很快!
Mysql有的使用它来存储一些比较大的文件,博客,图片,导致表很大,这样效率就很低下。
所以不是所有的数据都要存放关系型数据库中(Mysql),关系型数据库出现瓶颈了,Nosql数据库应用而生
什么是NoSQL?
NoSQL = Not only sql(不仅仅是sql)
关系型数据库:表格,列,行,有着固定的格式
泛指非关系型数据库,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发社区。NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的,很多数据类型数据如:用户的个人信息,社交网络,地理位置,不需要一个固定的格式,用键值对就可以控制Map<String,Object>
NoSQL特点
- 方便扩展(数据之间没有联系,很好扩展)
- 大数据量高性能(Redis一秒写8万次,读取11万,细粒度的缓存级别,性能比较高)
- 数据类型是多样的(不需要事先设计数据库)
传统的RDBMS
结构化组织
SQL
数据和关系都存在单独的表中 row col
严格一致性
基础事务
NoSQL
不仅仅是数据
没有固定的查询语言
键值对存储,列存储,文档存储,图形数据库(社交关系)
最终一致性
CAP和BASE理论
高性能,高可用,高可扩(三高)
2.NoSQL四大分类
1.KV键值对
- 新浪:Redis
- 美团:Redis + Tair
- 阿里,百度:Redis + Memecache
2.文档型数据库(bason格式和json一样)
MongoDB(一个基于分布式文件存储数据库,C++编写,用于处理大量文档,介于关系型和非关系型之间,也叫最复杂的菲关系型数据)
CouthDB
3.列存储数据库
HBase
4.图关系型数据库
不是存储图形,放的是关系,比如:朋友圈社交网络,广告推荐
Neo4j,InfoGrid
3.Redis入门
Redis(Remote Dictionary Server),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
当下最热门的NoSQL技术之一,能提供各种语言的API
Redis能干嘛?
1.内存存储,持久化,内存中是断电即失,所以说持久化很很重要(rdb,aof)
2.效率高,可以用于高速缓存
3.发布订阅系统
4.地图信息分析
5.计时器,计数器(浏览量)
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
下载地址:
官网:https://redis.io/
中文网:http://www.redis.cn/
Redis不推荐使用window,推荐linux版安装
常识命令
1.默认16个数据库(database 16),默认使用第0号数据库
2.切换数据库,例如:select 3
3.查看数据库大小:dbsize
4.查看当前数据库所有的key:key *
5.清空当前数据库:flushdb
清空所有数据库:flushall
6.退出:shutdown
7.判断key是否存在,例如:exists name
8.移除key ,例如:move name 1
9,设置某个key过期时间,例如:expire name 10
10.查看某个key剩余的过期时间,例如:ttl name
11.查看key的类型,例如:type name
Redis常用命令官方网站:http://www.redis.cn/commands.html
Redis是单线程的
Redis是基于内存操作,CPU不是Redis性能瓶颈,是内存和网络带宽
Redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文切换:耗时操作)
4.Redis五大数据类型
String,List,Hash,Set,Sorted Set
Redis不区分大小写命令
4.1.String(字符串)
- get
- set
设置值:set key1 v1
获取值:get key1
追加值,如果key不存在,则设置值操作:append key1 “hello”
获取字符串长度:strlen key1
加减法
数值加(减)1:incr views(decr views)
数值加(减)N:incrby views 10(decrby views 10)
字符串范围(range)
截取字符串[0,3]:getrange key 0 3
替换指定位置的字符串:setranage key 1 “xx”
setex和setnx
设置过期:setex key 30 “hello”(30秒后过期)
查看过期:ttl key
不存在再设置:setnx key "MongoDB"(在分布式锁中会经常用,如果key存在,就创建失败,不会覆盖)
批量set和批量get,msetnx是一个原子操作,要么一起成功,要么一起失败
mset k1 v1 k2 v2 k3 v3
mget k1 k2 k3
msetnx k1 v1 k4 v4(结果执行失败,因为k1存在)
设置对象,key是一个巧妙设计,格式:user:{id}:{filed}
mset user:1:name zhansan user:1:age 2
mget user:1:name user:1:age
getset用法,先get后set,结果显示get的值
getset db redis (如果不存在db,设置成功后,显示nil)
getset db MongoDB(设置成功后,显示redis )
场景如下:
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存
4.2.List(列表)
所有的命令都是L开头的
- Lpush
- Lrange
将一个值或者多个值,插入到列表的头部:
lpush list one
lpush list two
lpush list one
获取全部列表:lrange list 0 -1
将一个值或者多个值,插入到列表的尾部:Rpush list four
弹出命令:lpop {key}
左移除:lpop list
右移除:rpop list
列表长度:llen {key}
Llen list
移除list集合中指定个数的值:lrem {key} {num} {value}
lrem list 2 one
通过下标截取list集合中start到end的子集合,只剩下子集合:ltrim {key} {start} {end}
ltrim list 1 2
移除列表的最后一个元素,并移动到新的列表中:rpoplpush {key1} {key2}
rpoplpush mylist1 mylist2
将列表中指定下标的值更新成另外一个值,更新操作,不存在则报错:lset {key} {index} {value}
lset list 0 item
插入操作,在value2值之前插入value1:linsert {key1} before {value1} {value2}
插入操作,在value2值之后插入value1:linsert {key1} after {value1} {value2}
场景:
- 消息排队
- 消息队列
- 栈
4.3.Set(集合)
无序不重复集合,所有的命令都是S开头的
- Sadd
- Smembers
添加元素:Sadd {key} {value}
查看元素:Smembers {key}
判断该元素是否存在:Sismember {key}
统计集合个数:scard {key}
删除集合中指定的某个元素: srem {key} {value}
随机出N个元素:Srandmember {key} {num}
随机删除一个元素:Spop {key}
将一个集合的指定元素转移到另一个元素:Smove {key} {value} {value}
数字集合类
两个集合的元素差集,显示key1的差集值:Sdiff {key1} {key2}
两个集合的元素交集:Sinter {key1} {key2}
两个集合的元素并集:Sunion {key1} {key2}
场景
微博A用户的关注人,粉丝(不允许重复的)
4.4.Hash(哈希)
Map集合,key-Map<key,map>,本质跟String类型没啥区别,只是值变成了Map<key,map>
所有的命令都是H开头的
- Hset
- Hget
添加元素:Hset {key} {key1} {value1}
查看元素:Hget {key} {key1}
查看所有元素:Hgetall {key}
批量添加元素:Hmset {key} {key1} {value1} {key2} {value2} {key3} {value3}
批量查看元素:Hmget {key} {key1} {key2} {key3}
删除指定的元素:Hdel {key} {key1}
获取hash表的字段数量:Hlen {key}
判断元素是否存在:Hexists {key} {value1}
获取所有字段:Hkeys {key}
获取所有value:Hkeys {value}
删除集合中指定的某个元素: srem {key} {value}
还有Hsetnx(没有,则存,有,则失败)
场景:
- 变更的数据User对象,用户信息保存,经常变动的信息
- hash适合存储对象
- string更适合存储字符串
4.5.Zset(有序集合)
在set的基础上,增加一个标签,通过标签进行排序
所有的命令都是Z开头的
- Zadd
- Zrange
增加元素:Zadd {key} {flag} {value}
Zadd salary 2500 zhangsan
Zadd salary 1500 zhangsan2
查询所有元素:Zrange {key} 0 -1
元素从大到小排序:Zrevrange {key} 0 -1
元素按照负无穷到正无穷排序:Zrangebyscore {key} -inf +inf
元素按照负无穷到正无穷排序(带标签的):Zrangebyscore {key} -inf +inf withscores
Zrangebyscore {key} -inf 2500 withscores
Zrangebyscore {key} 0 2500 withscores
移除操作:Zrem {key} {value}
统计数量:Zcard {key}
获取指定标签区间的元素数量:Zcount {key} {start} {end}
zcount myset 1 3
场景:
- 存储班级成绩,
- 工资表排序
- 重要消息,加权重,排行榜