NoSQL概述

为什么要用NoSql

大数据时代,一般的数据库已经无法进行分析处理了

什么是NoSQL?

NoSQL = Not Only SQL

泛指非关系型数据库

NoSQL特点

1、方便扩展(数据之间没有关系,很好扩展)

2、大数据量、高性能(NoSQL的缓存记录级,是一种细粒度的缓存,性能比较高)

3、数据类型是多样性的(不需要实现设计数据库,随取随用)

4、传统的RDBMS和NoSQL

传统的RDBMSNOSQL
结构化组织不仅仅是数据
SQL没有固定的查询语言
数据和关系都存在单独的表中键值对存储、列存储、文档存储、图形数据库
操作,数据定义语言最终一致性
严格的一致性CAP定理、BASE(异地多活)
基础的事物高性能、高可用、高可扩

NoSQL的四大分类

KV键值对

  • Redis

文档型数据库

  • MongoDB
    • MongoDB是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量文档
    • MongoDB是一个介于关系型数据库和非关系型数据库的中间产品,是非关系型数据库中功能最丰富,最像关系型数据库的
  • ConthDB

列存储数据库

  • HBase

  • 分布式文件系统

图关系数据库

  • 存的不是图片,存的是关系,如朋友圈社交网络、广告推荐等

  • Neo4j

四者对比

image-20200610151151069

Redis入门

概述

Redis是什么?

(Remote Dictionary Server ),即远程字典服务

是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

也被人们称之为结构化数据库

image-20200610152350322

Redis能干嘛?

1、内存存储、持久化(rdb、aof)

2、效率高、可以用于高速缓存

3、发布订阅系统

4、地图信息分析

5、计时器、计数器(浏览量)

6、····

特性

1、多样的数据类型

2、持久化

3、集群

4、事务

····

学习中用到的东西

1、官网:https://redis.io/

2、中文网:http://www.redis.cn/

Linux安装

1、下载安装包,并上传至服务器(如果有的话)

image-20200610154601497

image-20200610154537416

2、解压安装包

压缩包放在opt目录

并解压

image-20200610160004272

解压完成

image-20200610160108040

3、进入解压后的Redis目录

image-20200610160240487

4、基本的环境安装

image-20200610160452937

image-20200610160553693

image-20200610164237733

5、Redis的默认安装路径

/usr/local/bin

6、在安装路径下新建myconfig文件夹,将redis.conf复制到此文件夹

image-20200610165102700

7、redis默认不是后台启动,修改配置文件,设置后台启动

vim打开文件

image-20200610165544526

此处改为yes

image-20200610165443462

最后

:wq保存退出

8、启动redis服务

通过指定的配置文件启动redis服务

image-20200610171120526

9、连接测试:

image-20200610173653606

image-20200610173833926

10、查看redis的进程是否开启

image-20200610174409585

11、关闭redis服务

image-20200610174605918

image-20200610174643324

测试性能

redis-benchmark是官方自带的压力测试工具,测试性能

命令格式:

redis-benchmark 命令参数

image-20200610175428452

简单测试:

#测试:100个并发连接,100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000

image-20200610182642386

基础知识

Redis有16个数据库

image-20200610194025053

默认使用的是第0个

可以使用select进行切换数据库

dbsize查看db大小

127.0.0.1:6379> select 3	#切换数据库
OK
127.0.0.1:6379[3]> 
127.0.0.1:6379[3]> dbsize	#查看db大小
(integer) 0
=======================================
127.0.0.1:6379[3]> set name zhiyu
OK
127.0.0.1:6379[3]> dbsize
(integer) 1
127.0.0.1:6379[3]> 
=======================================
127.0.0.1:6379[3]> select 7
OK
127.0.0.1:6379[7]> dbsize
(integer) 0
127.0.0.1:6379[7]> get name
(nil)
=======================================
127.0.0.1:6379[7]> select 3
OK
127.0.0.1:6379[3]> get name
"zhiyu"
127.0.0.1:6379[3]> 

keys *查看数据库中所有的key

flushdb清空当前数据库

flushall清空所有数据库

127.0.0.1:6379[3]> keys *	#查看数据库中所有的key
1) "name"
=======================================
127.0.0.1:6379[3]> flushdb	#清空当前数据库  flushall 清空所有数据库
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> 

Redis是单线程的

Redis是基于内存操作,CPU不是性能瓶颈

五大数据类型

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

Redis-Key

EXISTS key 查询key是否存在

127.0.0.1:6379> set name zhiyu
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> EXISTS name1
(integer) 0
127.0.0.1:6379> 

move key dbname 移动指定的key到指定的数据库中

127.0.0.1:6379> move name 1
(integer) 1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "name"

expire key seconds 设置指定key的过期时间,单位为秒

ttl name 查看指定key还有多长时间过期

127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name
"zhiyu"
127.0.0.1:6379> expire name 10
(integer) 1
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> 

type key 查看指定key的数据类型

127.0.0.1:6379> type name
string
127.0.0.1:6379> type age
string
127.0.0.1:6379> 

String

append key value 向指定key追加值,如果指定的key不存在,则新建这个key并set值

127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> append key1 hello
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> 

strlen key 获取指定key的长度

127.0.0.1:6379> strlen key1
(integer) 7
127.0.0.1:6379> 

incr key 将指定的key值+1

decr key 将指定的key值-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
(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
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> 

incrby key decrement(步长) 将指定key值增加指定步长

decrby key decrement(步长) 将指定key值减少指定步长

127.0.0.1:6379> incrby views 10
(integer) 10
127.0.0.1:6379> get views
"10"
127.0.0.1:6379> decrby views 10
(integer) 0
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> 

getrange key start end 截取指定key的指定位置的字符串,若为0,-1则代表全部

127.0.0.1:6379> set key1 hello,world
OK
127.0.0.1:6379> get key1
"hello,world"
127.0.0.1:6379> getrange key1 0 3
"hell"
127.0.0.1:6379> getrange key1 0 -1
"hello,world"
127.0.0.1:6379> 

setrange key offset(位置) value(修改的字符串)

127.0.0.1:6379> setrange key1 1 xxx
(integer) 11
127.0.0.1:6379> get key1
"hxxxo,world"
127.0.0.1:6379> 

setex key seconds value 设置键值对并设置过期时间

setnx key value 如果指定key不存在则设置指定值,如果存在则不操作

127.0.0.1:6379> setex key3 30 hello
OK
127.0.0.1:6379> ttl key3
(integer) 23
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx key4 redis
(integer) 1
127.0.0.1:6379> get key4
"redis"
127.0.0.1:6379> setnx key4 mongodb
(integer) 0
127.0.0.1:6379> get key4
"redis"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> 

mset [key value] 设置一组KV

mget [key] 获取一组key的值

msetnx [key value] 设置一组KV,如果key不存在则新建,key存在则创建失败,则后面的k4也会创建失败(原子性)

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 vv k4 v4
(integer) 0
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> 

这里的Key是一个巧妙的设计:user:{id}:{filed(属性名)}

127.0.0.1:6379> mset user:1:name zhiyu user:1:age 20
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhiyu"
2) "20"
127.0.0.1:6379> 

getset key value 先get再set

127.0.0.1:6379> getset key1 v1
(nil)
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> getset key1 v2
"v1"
127.0.0.1:6379> get key1
"v2"
127.0.0.1:6379> 

List

所有的List命令都是以L开头的

lpush key [value] 新建list并设置值,如果存在该list则追加值(向左边头部添加值)

rpush key [value] 新建list并设置值,如果存在该list则追加值(向右边尾部添加值)

lrange key start stop 查看指定下标的值;(0,-1)代表全部

127.0.0.1:6379> lpush list one two three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1
1) "three"
2) "two"
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> 

lpop key 移除左边(头部)第一个元素

rpop key 移除右边(尾部)第一个元素

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> lpop list
"three"
127.0.0.1:6379> rpop list
"right"
127.0.0.1:6379> lrange list
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> 

lindex key index(下标) 通过下标获取值

127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379> 

llen key 获取list的长度

127.0.0.1:6379> llen list
(integer) 2
127.0.0.1:6379> 

lrem key range(数量) value 移除指定数量的、指定的值

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> 

ltrim key start stop 修剪list

127.0.0.1:6379> rpush list hello hello1 hello2 hello3
(integer) 4
127.0.0.1:6379> ltrim list 1 2
OK
127.0.0.1:6379> lrange list 0 -1
1) "hello1"
2) "hello2"
127.0.0.1:6379> 

rpoplpush source destination 将一个list的尾部元素移动到另一个list的头部,如果新list不存在则创建

127.0.0.1:6379> lrange list 0 -1
1) "hello1"
2) "hello2"
127.0.0.1:6379> rpoplpush list mylist
"hello2"
127.0.0.1:6379> lrange list 0 -1
1) "hello1"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
127.0.0.1:6379> 

lset key index value 给指定list的指定下标设置值,相当于更新操作。当该list不存在或指定下标不存在时报错

127.0.0.1:6379> lset list 0 item0
(error) ERR no such key
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> lpush list item0
(integer) 1
127.0.0.1:6379> lset list 1 ltem1
(error) ERR index out of range
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> lset list 0 item000
OK
127.0.0.1:6379> lrange list 0 -1
1) "item000"
127.0.0.1:6379> 

linsert key BEFORE|AFTER pivot value 向指定value的前或后插入一个value

127.0.0.1:6379> rpush mylist hello world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> linsert mylist before world other
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
127.0.0.1:6379> 

小结:

  • List实际上是一个链表,before Node after ,left,right 都可以插值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除所有值,-> 空链表,也代表不存在
  • 在两边改动效率最高
  • 消息队列(Lpush Rpop),栈(Lpush Lpop)

Set

set中的值是不能重复的!

关于set的命令都是S开头

sadd key member [member ...] 新建一个Set

smembers key 查看指定set的全部value

127.0.0.1:6379> sadd myset hello zhiyu
(integer) 2
127.0.0.1:6379> smembers myset
1) "zhiyu"
2) "hello"
127.0.0.1:6379> 

sismember key member 判断某个value在不在指定set中

127.0.0.1:6379> sismember myset hello
(integer) 1
127.0.0.1:6379> sismember myset world
(integer) 0
127.0.0.1:6379> 

scard key 获取set中元素的个数

127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> 

srem key member [member ...] 移除指定set中指定的value

127.0.0.1:6379> srem myset hello
(integer) 1
127.0.0.1:6379> smembers myset
1) "zhiyu"
127.0.0.1:6379> 

srandmember key [count] 获取指定set中的随机元素,可指定一次获取的元素数量

127.0.0.1:6379> SMEMBERS myset
1) "zhiyu"
2) "zhiyu3"
3) "zhiyu2"
127.0.0.1:6379> SRANDMEMBER myset
"zhiyu3"
127.0.0.1:6379> SRANDMEMBER myset
"zhiyu"
127.0.0.1:6379> SRANDMEMBER myset
"zhiyu"

spop key [count] 随机移除元素

127.0.0.1:6379> SMEMBERS myset
1) "zhiyu"
2) "zhiyu3"
3) "zhiyu2"
127.0.0.1:6379> spop myset
"zhiyu2"
127.0.0.1:6379> spop myset
"zhiyu3"
127.0.0.1:6379> smembers myset
1) "zhiyu"
127.0.0.1:6379> 

smov source destination member 将指定的值移动到另一个set中

127.0.0.1:6379> sadd myset hello world zhiyu
(integer) 3
127.0.0.1:6379> sadd myset2 set2
(integer) 1
127.0.0.1:6379> smove myset myset2 zhiyu
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
127.0.0.1:6379> smembers myset2
1) "zhiyu"
2) "set2"
127.0.0.1:6379> 

sdiff key [key ...] 得到key1 和 key2 的差集,以key1的视角

sinter key [key ...] 得到交集

sunion key [key ...] 得到并集

127.0.0.1:6379> sadd key1 a b c
(integer) 3
127.0.0.1:6379> sadd key2 c d e
(integer) 3
127.0.0.1:6379> sdiff key1 key2
1) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2
1) "c"
127.0.0.1:6379> sunion key1 key2
1) "c"
2) "b"
3) "d"
4) "a"
5) "e"

Hash

Map集合, key-map(key-value)

Zset

Q.E.D.


ALL WILL BE CLEAR