NoSQL概述
NoSQL = Not Only SQL (不仅仅是SQL)
关系型数据库 : 表格 行 列
泛指非关系型数据库的 , 随着web2.0互联网的诞生 ! 传统的关系型数据库很难对付web2.0时代 ! 尤其是超大规模的高并发的社区 ! 暴露出来很多难以克服的问题 , NoSQL在当今大数据环境下发展的十分迅速 , Redis是发展最快的 , 而且是我们当下必须掌握的一个技术 !
很多的数据类型用户的个人信息 , 社交网络 , 地理位置 . 这些数据类型的存储不需要一个固定的格式 ! 不需要多余的操作就可以横向扩展的 ! Map<String,Object> 使用键值对来控制 !
NoSQL特点
- 方便扩展(数据之间没有关系 , 很好扩展!)
- 大数据量高性能 (Redis一秒写8万次 , 读取11万次 , NoSQL的缓存记录级 , 是一种细粒度的缓存 , 性能会比较高 ! )
- 数据类型是多样型的 ! ( 不需要事先设计数据库 ! 随取随用 ! 如果是数据量十分大的表 , 很多人就无法设计了 ! )
- 传统RDBMS 和 NoSQL
传统的 RDBMS (关系型数据库)
- 机构化组织
- SQL
- 数据和关系都存在单独的表中 row col
- 操作,数据定义语言
- 严格的一致性
- 基础的事务
- .....
NoSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储, 列存储, 文档存储, 图形数据库 (社交关系)
- 最终一致性
- CAP定理和BASE (异地多活)
- 高性能, 高可用, 高可扩
- ....
大数据时代的3V : 主要是描述问题的
- 海量Volume
- 多样Variety
- 实时Velocity
大数据时代的3高 : 主要是对程序的要求
- 高并发
- 高可拓
- 高性能
# 1.商品的基本信息信息
名称, 价格, 商家信息:
关系型数据库就可以解决了! MySQL/Oracle
淘宝内部的MySQL不是大家用的MySQL
# 2.商品的描述 评论 (文字比较多)
文档型数据库, MongoDB
# 3.图片
分布式文件系统 FastDFS
- 淘宝自己的 TFS
- Google的 GFS
- Hadoop HDFS
- 阿里云的 oss
# 4.商品的关键字 (搜索)
- 搜索引擎 solr elasticsearch
- ISerach: 多隆
# 5.商品热门的波段信息
- 内存数据库
- Redis Tair Memache...
# 6.商品的交易,外部的支付接口
- 三方应用
NoSQL的四大分类
KV键值对 :
- 新浪 : Redis
- 美团 : Redis + Tair
- 阿里 百度 : Redis + memecache
文档型数据库( bson格式 和json一样 ) :
- MongoDB ( 一般必须掌握 )
- MongoDB是一个基于分布式文件存储的数据库 , C++编写, 主要用来处理大量的文档 !
- MongoDB是一个介于关系型数据库和非关系型数据库的中间产品 ! MongoDB是非关系型数据库中功能最丰富, 最像关系型数据库的!
- ConchDb
列存储数据库
- HBase
- 分布式文件系统
图关系数据库
- 他不是存图形的, 放的是关系, 比如 : 朋友圈社交网络, 广告推荐!
- Neo4j, InfoGrid
Redis入门
概述
Redis是什么
Redis(Remote Dictionary Server ),即远程字典服务
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
免费和开源 ! 是当下最热门的NoSQL技术之一 ! 也被人们称之为结构化数据库 !
Redis能干嘛
- 内存存储, 持久化, 内存是断电即失, 所以说持久化很重要( rdb, aof )
- 效率高, 可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器, 计数器( 浏览量! )
- …
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
…
官网 : http://www.redis.cn/
windows在GitHub下载
Windows安装
GitHub下载 : https://github.com/MicrosoftArchive/redis/releases
解压安装即可
开启Redis,双击redis-server.exe即可
连接Redis,打开redis-cli.exe即可
Windows下使用确实简单, 但是Redis推荐我们使用Linux去开发使用!
Linux安装
-
下载安装包 : http://download.redis.io/releases/redis-6.0.6.tar.gz
-
上传到Linux服务器中(程序一般放在/opt目录下)
-
解压安装包
tar -zxvf redis-6.0.6.tar.gz
解压完成就有Redis目录了
- 进入Redis目录可以看到Redis的配置文件
-
基本的环境安装
Redis6以上需要gcc版本在7以上。
依次运行以下命令安装环境, 遇到问题一直y即可
yum install gcc-c++ sudo yum install centos-release-scl sudo yum install devtoolset-7-gcc* scl enable devtoolset-7 bash make make make install
没报红,没error,就算成功了
- Redis默认安装路径 /usr/local/bin
-
将Redis配置文件复制到当前目录下
mkdir myconfig cp /opt/redis-6.0.6/redis.conf myconfig/
-
redis默认不是后台启动的, 修改配置文件 !
yum -y install vim* # 先安装vim 有可以忽略 vim redis.conf # 编辑redis.conf :/daemonize # 按:进入命令模式 /daemonize查找daemonize i # 按i 进入插入模式 再把no改为yes即可 Esc # 按Esc退出编辑模式 不行就按delete键或者按住Shift+两次Z :wq # 按:进入命令模式 wq保存退出
-
启动Redis服务
cd .. #返回bin目录 ln -s /usr/local/bin/redis-server /usr/bin/redis-server #建立redis-server软连接,否则找不到命令 ln -s /usr/local/bin/redis-cli /usr/bin/redis-cli #建立redis-cli软连接 redis-server myconfig/redis.conf #启动Redis服务 redis-cli -p 6379 #使用客户端连接
-
退出Redis
shutdown exit
-
查看Redis进程
ps -ef|grep redis
性能测试
redis-benchmark是一个压力测试工具!
官方自带的性能测试工具
redis-benchmark + 命令
测试
# 测试: 100并发连接 10000个请求
ln -s /usr/local/bin/redis-benchmark /usr/bin/redis-benchmark #建立软连接否则找不到命令
redis-server myconfig/redis.conf #开启Redis
redis-benchmark -h localhost -p 6379 -c 100 -n 10000 #测试连接
查看分析
基础知识
Redis默认有16个数据库
默认使用第0个
可以使用select进行切换数据库
127.0.0.1:6379> select 3 # 切换到第3个数据库
OK
127.0.0.1:6379[3]> dbsize # 查看数据库大小
(integer) 0
清除当前数据库 flushdb
清除全部数据库的内容 flushall
127.0.0.1:6379[3]> keys * # 查看所有的key
1) "name"
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> exists age #查看age是否存在
(integer) 1
127.0.0.1:6379> move name 1 #将数据移动到1号数据库
(integer) 1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "name"
127.0.0.1:6379[1]> expire name 5 #设置数据5秒后过期,过期自动删除
(integer) 1
127.0.0.1:6379[1]> ttl name #查看过期时间,-2代表过期了
(integer) -2
127.0.0.1:6379[3]> flushdb # 清空当前数据库
OK
127.0.0.1:6379[3]> keys *
(empty array)
127.0.0.1:6379[3]> flushall # 清空全部数据库(不止当前数据库)
OK
Redis主线程是单线程的
Redis在4.0之前单线程依然快的原因:基于内存操作、数据结构简单、IO多路复用和非阻塞IO、避免了不必要的线程上下文切换。
并且在Redis4.0开始支持多线程,主要体现在大数据的异步删除方面,例如:unlink key、flushdb async、flushall async等。
而Redis6.0的多线程则增加了对IO读写的并发能力,用于更好的提升Redis的性能。
Redis是基于内存操作, CPU不是Redis性能瓶颈, Redis的瓶颈是根据机器的内存和网络宽带.
五大数据类型
Redis-key
127.0.0.1:6379> set age 1 #set key
OK
127.0.0.1:6379> exists age #查看age是否存在
(integer) 1
127.0.0.1:6379> move name 1 #将数据移动到1号数据库
(integer) 1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys * # 查看所有的key
1) "name"
127.0.0.1:6379[1]> expire name 5 #设置数据5秒后过期,过期自动删除
(integer) 1
127.0.0.1:6379[1]> ttl name #查看过期时间,-2代表已过期,-1永不过期
(integer) -2
127.0.0.1:6379> type age #查看key的类型
string
127.0.0.1:6379[3]> flushdb # 清空当前数据库
OK
127.0.0.1:6379[3]> keys *
(empty array)
127.0.0.1:6379[3]> flushall # 清空全部数据库(不止当前数据库)
OK
遇到不会的命令上官网查看:http://www.redis.cn/commands.html
String(字符串)
127.0.0.1:6379> set k1 v1 #set key
OK
127.0.0.1:6379> get k1 #get key
"v1"
127.0.0.1:6379> append k1 "hello" #追加字符串到v1的后面,如果key不存在则set一个key
(integer) 7
127.0.0.1:6379> get k1
"v1hello"
127.0.0.1:6379> strlen k1 #查看字符串的长度即v1的长度
(integer) 7
127.0.0.1:6379> append k1 "Lance"
(integer) 12
127.0.0.1:6379> strlen k1
(integer) 12
127.0.0.1:6379> get k1
"v1helloLance"
127.0.0.1:6379> exists k1 # 判断可以是否存在
(integer) 1
##############################################################
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # views+1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views # views-1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> incrby views 10 #可以设置步长 views+10
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decrby views 10 #可以设置步长 views-10
(integer) 1
127.0.0.1:6379> get views
"1"
##############################################################
127.0.0.1:6379> set key1 "hello,Lance" # 设置key1的值
OK
127.0.0.1:6379> getrange key1 0 4 # 截取字符串[0,4] 相当于substring(key1,0,4)
"hello"
127.0.0.1:6379> getrange key1 0 -1 # 截取全部的字符串
"hello,Lance"
127.0.0.1:6379> setrange key1 5 XX # 从下标5开始替换成XX 相当于key1.replace(5,7,XX)
(integer) 11
127.0.0.1:6379> get key1
"helloXXance"
###############################################################
#setex (set with expire) #设置过期时间
#setnx (set if not exist) # 不存在设置 (在分布式锁中会常常使用)
127.0.0.1:6379> setex key3 10 "hello" # set key3 并设置过期时间10s 值hello
OK
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx key4 "hello" # 不存在则创建key4
(integer) 1
127.0.0.1:6379> keys *
1) "key4"
2) "key1"
127.0.0.1:6379> setnx key4 "Lance" #存在则失败
(integer) 0
127.0.0.1:6379> get key4
"hello"
###############################################################
127.0.0.1:6379> flushdb # 清空当前数据库
OK
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 批量set
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 # 批量get
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 # 如果有一个存在则set失败(是一个原子性的操作,都成功,都失败)
(integer) 0
127.0.0.1:6379> get k4
(nil)
###############################################################
#对象
set user:1 {
name:Lance,age:18} #设置一个user:1 对象 值为json字符来保存一个对象
#user:{id}:{filed}
127.0.0.1:6379> mset user:1:name Lance user:1:age 18 #本质是设置key为user:1:name值Lance
OK
127.0.0.1:6379> mget user:1:name user:1:age #获取key user:1:name和user:1:age的值
1) "Lance"
2) "18"
127.0.0.1:6379> keys *
1) "k1"
2) "user:1:name"
3) "k2"
4) "k3"
5) "user:1:age"
127.0.0.1:6379>
###############################################################
# getset 先get再set
127.0.0.1:6379> getset db v1 #先获取db的值再设置db的值为v1
(nil)
127.0.0.1:6379> get db
"v1"
127.0.0.1:6379> getset db v2
"v1"
127.0.0.1:6379> get db
"v2"
String类似的使用场景 : value除了是字符串还能是数字
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储
List(列表)
基本的数据类型, 列表
在Redis里面, 可以把list玩成, 栈, 队列, 阻塞队列
所以的list命令都是用l开头的
127.0.0.1:6379> lpush list one #将一个值或者多个值,插入到列表的头部 (左)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 1 #通过区间获取值[0,1]
1) "three"
2) "two"
127.0.0.1:6379> lrange list 0 -1 #获取list所有的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> Rpush list right #将一个值或者多个值,插入到列表的尾部 (右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
###############################################################
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"<