灵感来自视频作者(狂胜说java)https://www.bilibili.com/video/BV1S54y1R7SB?p=35
NoSql概述
为什么要用NoSQL
1 单机时代
90年代,一个网站的访问量不会很大,单个数据库足以应对,那这种网站的瓶颈在哪呢?
- 数据量一大,一个数据库是放不下的。
- 数据的索引(300万)一个机器内存也是放不下的。
- 访问量(读写混合),一个服务器处理不了
2 Memcached缓存+MySQL+垂直拆分 读写分离
80%的情况都在读,每次都从mysql里查就很影响效率,所以我们就希望每次从缓存中查询数据,这样就可以提高查询效率
3.分库分表+水平拆分+MySQL集群
数据库引擎:
MyISAM: 表锁 十分影响效率,查询一条数据,就要把整张表锁定
InnoDB : 行锁
4.当今大数据时代
为什么要用NoSQL
用户的个人信息、社交网络、地理位置,都会爆发式的产生数据,NoSQL会很好的解决这一问题
什么是NoSQL
NoSQL=Not only SQL
关系型数据库:表格 行 、列
NoSQL泛指非关系型数据库,随着web2.0时代的诞生,传统的关系型数据库是难以应对web2.0的,NoSQL在当今大数据时代发展十分迅速,redis是程序员必会的一个技能。
很多用户的数据比如地理位置、个人信息、 社交网络都没有固定的格式,这些数据可以通过Map<String,Object>数据结构来存储
NoSQL特点
解耦!
-
方便扩展(数据之间没有关系,横向扩展)
-
大数据量高性能(redis 1秒读11w次,1秒写1w次,NoSQL的缓存记录,细粒度的缓存)
-
数据是各式各样的(不需要事先设计数据库,随去随用,如果是数据量十分大的表,很多人是不能很好的设计数据库的)
-
传统的RDBMS和NoSQL
传统的RDBMS:
- 结构化组织
- sql
- 数据和关系都存在单独的表中
- 数据定义语言DDL
- 严格的一致性
- 基础的事务
- …
NoSQL
不仅仅是数据库
没有i固定的查询语言
键值对存储,列存储,文档存储,图形数据库
最终一致性
CPA定理和BASE(异地多活)
高性能 高可扩 高可用
NoSQL的四大分类
-
键值对
- 新浪 redis
- 美团 redis+Tair
- 阿里、百度 Redis+Memecach
-
列存储数据库:
- HBase
- 分布式文件系统
-
文档型存储:(bson格式的,和json一样)
MongoDB(一般必须要掌握)
- MongoDB是基于分布式文件存储的数据库,C++编写,用来存储大型文档 - MongoDB是介于关系型数据库和非关系型数据库之间的中间件产品!MongoDB是所有非关系型数据库中功能最丰富,最像关系型数据库的。
-
图关系数据库:
社交网络
Redis入门
什么是Redis
Remote dictionary Server 即远程字典服务
是一个开源的使用c语言编写的、支持网络、可基于内存也可以基于持久化的日志型、key-value数据库,提供多种语言的API
Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的文件中,并在此基础上实现了主从复制(Master-slave)
Redis能干吗
- 内存存储、持久化存储,内存存储断电即失,所以持久化存储是十分重要的(rdb、aof持久化策略)
- 效率高,可用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量)
- …
Redis安装
WINDOWS:
在官网http://redis.io下载zip,解压即可
Redis推荐使用Linux安装
Linux下安装:
宝塔面板
- 解压压缩包
-
进入redis-6.0.9 执行 yum install gcc-c++
-
执行make
-
执行make install
-
安装完毕
redis默认安装路径:
-
redis默认不是后台启动
-
通过指定的配置文件启动
-
客户端启动
-
查看进程是否开启
-
退出redis
benchmark压力测试
安装jkd1.8
-
解压安装
-
修改配置文件
-
执行
source /etc/profile
Redis基础知识
redis有16个数据库,默认使用第0个,可以使用select 3切换数据库
1、切换数据库
select(3)
2、查看数据库大小
dbsize
3、查看所有的key
keys *
4、删除所有key
flushdb
5、清空所有数据库
flushall
redis是单线程的
redis是单线程的为啥还这么快?
redis是c语言写的,是将数据直接放进内存的,所以使用单线程操作效率就是最高的,对于多线程而言,频繁的上下文切花则会消耗更多的资源。
五大数据类型
Redis key
127.0.0.1:6379> type name #查看key的类型
string
127.0.0.1:6379> expire name 10 #设置key的有效时间,单位秒
(integer) 1
127.0.0.1:6379> ttl name # 查看key的剩余有效时间
(integer) -2
127.0.0.1:6379> keys * #查看所有key
1) "mail"
2) "age"
127.0.0.1:6379> exists name #查看key是否存在 0表示不存在 1表示存在
(integer) 0
127.0.0.1:6379> exists age
(integer) 1
127.0.0.1:6379> move name 1 #移除当前key
(integer) 0
String
127.0.0.1:6379> append abc efg #追加字符串 如果key不存在则新建 (integer) 6 127.0.0.1:6379> get abc "abcefg" 127.0.0.1:6379> set views 0 OK 127.0.0.1:6379> incr views # 自动加一 (integer) 1 127.0.0.1:6379> incr views 127.0.0.1:6379> decr views #自动减一 (integer) 1 127.0.0.1:6379> incrby views 5 #自增步长 (integer) 6 decrby 5 views #自减步长 ################################################################ #字符串范围 127.0.0.1:6379> set str helloword OK 127.0.0.1:6379> getrange str 1 5 #取下标1-5的字符串 "ellow" 127.0.0.1:6379> getrange str 0 -1 # 获取全部字符串 "helloword" setrange str 2 xxx #字符串替换 从下标为2的地方开始替换 (integer) 9 127.0.0.1:6379> get str "hexxxword" ################################################################ setex (set expire)#设置过期时间 setnx (set if not exist)#如果不存在在设置 分布式锁 setex k1 30 redis #设置k1为 redis 有效时间30秒 setnx k2 redis #设置k2位redis 如果k2不存在则创建,否则创建失败 ################################################################ mset #同时设置多个值 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 OK 127.0.0.1:6379> keys * 1) "k3" 2) "k2" 3) "k1" 127.0.0.1:6379> msetnx k5 v5 k6 v6 #msetnx 原子性操作,如果key存在,则全部无法创建 (integer) 0 ################################################################ #对象 127.0.0.1:6379> set user:1 { name:zhang,age:1} #存一个user对象,key为user:1,value为json OK 127.0.0.1:6379> mset user:1:name zhangshan user:1:age 10#存一个user,id=1,name=张三, #age=10 OK 127.0.0.1:6379> keys * 1) "user:1:name" 2) "user:1:age" ################################################################ #getset 如果不存在返回niio 127.0.0.1:6379> getset db redis (nil) 127.0.0.1:6379> get db "redis" 127.0.0.1:6379> getset db mongodb #如果存在 返回value,在设置新的value "redis" 127.0.0.1:6379> get db "mongodb" 127.0.0.1:6379>
List
所有的list命令是以“L***开头的,我们可以把list玩成***栈、队列、阻塞队列(redis不区分大小写)
#添加命令
#lpush 从左边push,类似栈
127.0.0.1:6379> lpush list a
(integer) 1
127.0.0.1:6379> lpush list b
(integer) 2
127.0.0.1:6379> lpush list c
(integer) 3
127.0.0.1:6379> lpush list d
(integer) 4
127.0.0.1:6379> lrange list 0 -1 #获取全部的值,也可以获取部分值 lrange list 0 3
1) "d"
2) "c"
3) "b"
4) "a"
#rpush 从右边push
127.0.0.1:6379> rpush list e
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "e"
################################################################
#移除命令
127.0.0.1:6379> lrange list 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "e"
127.0.0.1:6379> lpop list #从左边开始pop
"d"
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
3) "a"
4) "e"
127.0.0.1:6379> rpop list #从右边开始pop
"e"
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
3) "a"
################################################################
#获取下标为1的list元素
127.0.0.1:6379> lindex list 1
"b"
################################################################
#获取list元素个数
127.0.0.1:6379> llen list
(integer) 3
################################################################
#移除指定的值 lrem
127.0.0.1:6379> lrange list 0 -1
1) "k3"
2) "k6"
3) "k5"
4) "k4"
5) "k3"
6) "k2"
127.0.0.1:6379> lrem list 2 k3
(