">Nosql概述
为什么要用Nosql
- 单机MySQL的年代
90年代,一个基本的网站访问量一般不会太大,单个数据库完全足够!
那个时候,更多的去使用静态网页 Html ~ 服务器根本没有太大的压力!
思考一下,这种情况下:整个网站的瓶颈是什么?
- 数据量如果太大,一个机器放不下了!
- 数据的索引(B+tree),一个机器内存也放不下
- 访问量(读写混合),一个服务器承受不了~
如果你开始出现以上的三种情况之一,那么你就必须要晋级!
- Memcached(缓存)+MySQL+垂直拆分
网站80%的情况都是在读,每次都要去查询数据库的话就十分的麻烦!所以说我们希望减轻数据的压力,我们可以使用缓存来保存效率!
发展过程:优化数据结构和索引–》文件缓存(IO)–》Memcached(当时最热门的技术!)
- 分库分表+水平拆分+MySQL集群
技术和业务在发展的同时,对人的要求也越来越高!
- 如今最近的年代
为什么要用NoSQL!
用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长!
这时候我们就需要使用NoSQL数据库的,NoSQL可以很好的处理以上的情况!
什么是NoSQL
NoSQL = non-relational(非关系型数据库),随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区!暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速。Redis是发展最快的,而且是我们当下必须要掌握的一个技术!
NoSQL特点
方便扩展(数据之间没有关系,很好扩展!)
大数据量高性能(Redis一秒可以写8万次,读取11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)
数据类型是多样型的!(不需要事先设计数据库!随取随用!如果是数据量十分大的表,很多人就无法设计了!)
传统的EDBMS和NoSQL
1
2
3
4
5
6
7
8传统的 RDBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表中 row col
- 操作,数据定义语言
- 严格的一致性
- 基础的事务
- ......1
2
3
4
5
6
7
8NoSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性
- CAP定理和BASE(异地多活)初级架构师!
- 高性能,高可用,高可扩
- ....
了解:3V+3高
大数据时代的3V:主要是描述问题的
- 海量Volume
- 多样Variety
- 实时Velocity
大数据时代的3高:主要是对程序的要求
- 高并发
- 高可扩(随时水平拆分)
- 高性能(保证用户体验和性能)
真实的公司中的时间:NoSQL+RDBMS一起使用才是最强的,阿里巴巴的架构
阿里巴巴演进分析
大型互联网应用问题:
- 数据类型太多了!
- 数据源繁多,经常重构!
- 数据要改造,大面积改造!
解决问题:
UDSL热点缓存设计
NoSQL的四大分类
KV键值对:
- 新浪:Redis
- 美团:Redis+Tair
- 阿里、百度:Redis+memcache
文档型数据库(bson格式和json一样):
- MongoDB(一般必须要掌握)
- MongoDB是一个基于分布式的文件存储的数据库,C++编写,主要用来处理大量的文档!
- MongoDB是一个介于关系型数据库和非关系型数据库中间的产品!MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的!
- ConthDB
列存储数据库
- HBase
- 分布式文件系统
图形关系数据库
- 它不是存图形,放的是关系,比如:朋友圈社交网络,广告推荐!
- Neo4j,Graph
Redis入门
概述
Redis是什么?
Redis(Remote Dictionary Server),即远程字典服务!
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。免费和开源!是放下最热门的NoSQL技术之一!也被人们称之为结构化数据库!
Redis能干嘛?
- 内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb、aof)
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量!)
- …
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
Windows安装
- 下载安装包
- 下载完毕得到压缩包
- 解压到自己电脑上的环境目录下的就可以的!
- 开启 redis,运行服务即可!
Windows下使用确实简单,但是Redis推荐我们使用Linux去开发使用!
Linux安装
下载安装包!
redis-6.2.1.tar.gz
解压Redis的安装包!程序 /opt
进入解压后的文件,可以看到 redis 的配置文件
基本的环境安装
1
2
3
4
5yum install gcc-c++
make
make install #确认redis 的默认安装路径
usr/local/bin
将 redis 配置文件复制到我们当前目录下,可以创建一个配置文件夹如wangconfig
redis 默认不是后台启动的,修改自定义配置redis文件
1
daemonize yes //守护进程模式启动
启动 redis 服务!
1
redis-server wangconfig/redis.conf
使用Redis客户端进行连接
1
2
3redis-cli -p 6379
#查看所有的key
keys *查看redis的进程是否开启
1
2
3
4[root@touchingwang ~]# ps -ef|grep redis
root 20985 1 0 14:47 ? 00:00:00 redis-server 127.0.0.1:6379
root 21058 15176 0 14:48 pts/0 00:00:00 redis-cli -p 6379
root 21263 21221 0 14:51 pts/1 00:00:00 grep --color=auto redis如何关闭redis服务呢?
1
2127.0.0.1:6379> shutdown
not connected> exit再次查看进程是否存在
1
2[root@touchingwang ~]# ps -ef|grep redis
root 21323 21221 0 14:53 pts/1 00:00:00 grep --color=auto redis后面我们会使用单机多redis启动集群测试!
测试性能
redis-benchmark是一个压力测试工具!
官方自带的性能测试工具!
我们来简单测试下:
1 | # 测试:100个并发连接 100000请求 |
如何查看这些分析呢!
1 | #测试的每一个请求格式都如下 |
基础的知识
redis 默认有16个数据库,可以在redis.conf
中看到databases 16
可以使用 select 进行切换数据库
1 | 127.0.0.1:6379> select 3 |
清空当前数据库flushdb
清空全部数据库的内容flushall
思考:为什么 redis 是6379?(了解一下即可!)
redis 是单线程的!
明白Redis是很快的,官方表示,Redis是基于内存操作的,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!所以就使用了单线程!
Redis 是C 语言写道,官方提供的数据为 100000+ 是QPS,完全不比同样是使用 key-value 的Mamecache差!
- 误区1:高性能的服务器一定是多线程的?
- 误区2:多线程(CPU上下文切换!)一定比单线程效率低!
先去CPU》内存》硬盘的速度要有所了解!
核心:redis 是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!!!),对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!
五大数据类型
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)。
我们现在讲解的命令大家一定要全部记住,后面我们使用SpringBoot。Redis,所有的方法就是这些命令!单点登录
Redis-Key
1 | keys * #查看所有的key |
后面如果遇到不会的命令,可以去官网查看帮助文档
String(字符串)
90%的Java程序员 redis 只会使用一个String类型!
1 | set key1 v1 #设置值 |
数据结构是相同的!
String类似的使用常见:value除了是我们的字符串还可以是我们的数字!
- 计数器
- 统计多单位的数量
uid:829797897:follow 0
- 粉丝数
- 对象缓存存储
List
基本的数据类型,列表
在redis里面,我们可以把list玩成,栈,队列,阻塞队列!
所有的list命令都是用l开头的
1 | ################################################### |
小结
- 它实际上是一个链表,before Node after,left,right都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增乃荣
- 弱国移除了所有值,空链表,也代表不存在!
- 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~
消息排列!消息队列 (Lpush Rpop),栈(Lpush Lpop)!
Set(集合)
set中的值是不能重复的!
1 | ##################################################### |
微博,A用户将所有关注的人放到一个set集合中!将它的粉丝也放在一个集合中!
共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)
Hash(哈希)
Map集合,key-map!这时候这个值是一个mao集合!本质和String类型没有太大区别,还是一个简单的key-value!
set myhash field touchingwang
1 | 127.0.0.1:6379> hset myhash field kuangshen #set一个具体key-value |
hash变更的数据 user name age,尤其是用户信息之类的,经常变动的信息!hash更适合于对象的存储。String更适合字符串存储!
hset user:1 name kuangshen
Zset(有序集合)
在set的基础上,增加了一个值,set k1 v1 zset k1 score v1
1 | 127.0.0.1:6379> zadd myset 1 one #添加一个值 |
其余的一些API,通过我们的学习,剩下的如果工作中有需要,这个时候你可以去查查看官方文档!
案例思路:set 排序 存储班级成绩表,工资表排序!
普通消息,1,重要消息,2,带权重进行判断!
排行榜应用实现,取Top N
三种特殊数据类型
geospatial地理位置
朋友的定位,附近的人,打车举例计算?
Redis的Geo在Redis3.2版本就推出了!这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人!
只有六个命令
getadd
1 | # getadd 添加地理位置 |
geopos
获得当前定位:一定是一个坐标镇!
1 | 127.0.0.1:6379> GEOPOS china:city chongqi #获取指定的城市的经度,纬度! |
geodist
两人之间的距离
单位:
- m:表示单位为米
- km:表示单位为千米
- mi:表示单位为英里
- ft:表示单位为英尺
1 | 127.0.0.1:6379> GEODIST china:city beijin shanghai |
georadius 以给定的经度为中心,找出某一半径内的元素
找附近的人?(获得所有附近的人的地址,定位!)通过半径来查询!
获得指定数量的人,200
1 | 127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord [count 1] |
georadiusbymember
1 | # 找出位于指定元素周围的其他元素! |
geohash命令 - 返回一个或多个位置的geohash表示
该命令将返回11个字符的geohash字符串!
1 | 127.0.0.1:6379> GEOHASH china:city beijin chongqi |
GEO 底层的实现原理其实就是Zset!我们可以使用Zset命令来操作geo!
1 | 127.0.0.1:6379> ZRANGE china:city 0 -1 #查看地图中全部的元素 |
Hyperloglog
什么是基数?
A{1,3,5,7,8,7} B{1,3,5,7,8}
基数(不重复的元素) A为5,可以接收误差!
简介
Redis2.8.9版本就更新了Hyperloglog数据结构!
Redis Hyperloglog 基数统计的算法!
优点:占用的内存是固定的,2^64 不同的元素的技术,只需要费 12KB内存!如果要从内存角度来比较的话 Hyperloglog 首选
网页的UV(一个人访问一个网站多次,但是还是算作一个人!)
传统的方式,set 保存用户的 id,然后就可以统计 set 中的元素数量作为标准判断!
这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了技术,而不是保存用户id;
0.81%错误率!统计UV任务,可以忽略不计的!
测试使用
1 | 127.0.0.1:6379> PFADD mykey a b c d e f g h i j #创建第一组元素 mykey |
如果允许容错,那么一定可以使用 Hyperloglog!
如果不允许容错,就使用 set 或者自己的数据类型即可!
Bitmaps
位存储
统计用户信息,活跃,不活跃!登录、未登录!打卡,365打卡!两个状态的,都可以使用Bitemaps!
Bitmaps 位图,数据结构!都是操作二进制位来进行记录,就只有0和1两个状态!
使用bitmap 来记录周一到周日的打卡!
周一:1 周二:0 周三:0 周四:1……
1 | 127.0.0.1:6379> setbit sign 0 1 |
事务
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!
一次性、顺序性、排他性!执行一系列的命令!
1 | --- 队列 set set set 执行--- |
==Redis事务没有隔离级别的概念==
所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!Exec
Redis单条命令是保存原子性的,但是事务不保证原子性!
redis 的事务:
- 开启事务(multi)
- 命令入队()
- 执行事务()
正常执行事务!
1 | 127.0.0.1:6379> multi #开启事务 |
放弃事务!
1 | 127.0.0.1:6379> MULTI #开启事务 |
编译型异常(代码有问题!),事务中所有的命令都不会被执行!
1 | 127.0.0.1:6379> MULTI |
运行时异常(1/0),如果事务队列中存在语法性错误,那么执行命令的时候,其他命令可以正常执行的
1 | 127.0.0.1:6379> set k1 "v1" |
监控!
悲观锁:
- 很悲观,什么时候都不会出问题,无论做什么都会加锁!
乐观锁:
- 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据,version!
- 获取version
- 更新的时候比较 version
redis 测监视测试
1 | 127.0.0.1:6379> set money 100 |
测试多线程修改值,使用watch 可以当作redis的乐观锁操作!
1 | 127.0.0.1:6379> watch money |
Jedis
我们要使用Java来操作 Redis
什么是jedis 是Redis官方推荐的java连接开发工具!使用 java 操作 Redis 中间件!
如果你要使用java操作redis,那么一定要对jedis十分的熟悉!
测试
1、导入对应的依赖
1 | <!--导入jedis的包--> |
2、编码测试:
- 连接数据库
- 操作命令
- 断开连接!
1 | package com.wang; |
远程连接可能会出现的问题
- 开启安全组策略6379,bing注释只留一个,受保护的设置为no,防火墙关掉,重启
- 设置requirepass密码,登录查看是否修改成功
常用的API
对一些常用命令的操作
1 | public class TestPing { |
对 String 操作的命令
1 | public class TestPing { |
对 List 操作的命令
对 Set操作的命令
对 Hash操作的命令
对 Zset操作的命令
所有的API命令就是我们对应的上面学习的指令,一个都没有变化!
事务
1 | Jedis jedis = new Jedis("**.**.**.**", 6379); |
SpringBoot整合
SpringBoot 操作数据:Spring-data jdbc monodb redis!
SpringData 也是和 SpringBoot齐名的项目!
说明:在Springboot2.x之后,原来使用的jedis被替换为了lettuce?
jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool连接池!BIO
lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据,更像NIO模式
整合测试一下
1、导入依赖
1 | <!--操作redis--> |
2、配置连接
1 | # 配置redis |
3、测试
1 |
|
所有的对象,都需要序列化
默认的序列化方式是JDK序列,我们可能会使用json来序列化!
关于对象的保存:在企业中,所有的 pojo 都会序列化!我们来编写一个自己的RedisTemplate
1 |
|
所有的redis操作,其实对于java开发人员来说,更重要的是去理解redis的思想和每一种数据结构的用户和作用场景!
redis系列来自b站up主狂神说Java https://www.bilibili.com/video/BV1S54y1R7SB