首页 > 技术文章 > 概述

tang321 2021-05-10 18:43 原文

NoSQL数据库

NoSQL(Not Only SQL),即“不仅仅是SQL”,泛指非关系型的数据库
NoSQL不依赖业务逻辑方式存储,以简单的key-value模式存储,增加了数据库的扩展能力


特点

  • 不遵循SQL标准
  • 不支持ACID
  • 远超于SQL的性能

 

NoSQL适用场景

  • 对数据高并发的读写
  • 海量数据的读写
  • 对数据高可扩展性

 

NoSQL不适用场景

  • 需要事务支持
  • 基于sql的结构化查询存储,处理复杂的关系

 

下载安装

进入官网下载:https://redis.io/

使用 WinSCP+Putty 将压缩包上传至服务器(位置:/opt/redis/redis-6.2.3.tar.gz)并进行远程连接服务器

 

安装编译环境

yum install gcc

  

查看安装是否成功

gcc --version

  

解压

tar -zxvf redis-6.2.3.tar.gz

  

解压后进入目录

cd redis-6.2.3

  

执行make命令

make

 

完成安装

make install

  

默认安装目录:/usr/local/bin
查看默认安装目录:
redis-benchmark:性能测试工具
redis-check-aof:修复有问题的AOF文件
redis-check-rdb:修复有问题的dump.rdb文件
redis-sentinel:redis集群使用
redis-server:redis服务器启动命令
redis-cli:客户端操作入口

 

启动方式

前台启动(不推荐):前台启动命令行窗口不能关闭,否则服务器停止
后台启动(推荐)

 

前台启动

redis-server

  

后台启动

1、拷贝一份 redis.conf

cp /opt/redis/redis-6.2.3/redis.conf /etc/redis.conf

2、将 /etc/reids.conf 中 daemonize no 改为 daemonize yes

3、启动

redis-server /etc/redis.conf

4、查看进程

ps -ef | grep redis

  

 

关闭 Redis

单实例关闭   redis-cli shutdown
多实例关闭,指定端口关闭   redis-cli -p 6379 shutdown

 

Redis相关知识

默认16个数据库,类似数组下标从0开始,默认使用0号库
使用命令 select <dbid> 来切换数据库,如:select 8
统一密码管理,所有库同样密码

dbsize 查看当前数据库的key的数量
flushdb 清空当前库
flushall 清空全部库

 

单线程+多路IO复用技术

多路指的是多个socket连接,复用指的是复用同一个线程
采用多路IO复用技术可以让单个线程高效地处理多个连接请求

 

redis的原子性

Redis的原子操作指的是不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch(切换到另一个线程)
在单线程中,能够在单条指令中完成的操作都可以认为是原子操作,因为中断只能发生于指令之间
在多线程中,不能被其他线程打断的操作就叫原子操作
Redis的原子性主要得益于单线程

key操作

keys *     查看当前库所有key
exists key   判断某个key是否存在,0不存在,1存在
type key   查看key的类型
del key    删除指定key数据
unlink key   非阻塞删除,仅将key数据从keyspace元数据中删除,真正的删除会在后续异步操作
expire key 10   为指定的key设置过期时间,这里是10s
ttl key      查看还有多少秒过期,-1表示永不过期,-2表示已经过期

 

常用数据类型

常用五大数据类型

  • 字符串String
  • 列表List
  • 集合Set
  • 哈希Hash
  • 有序集合Zset

String

一个Redis字符串value最多可以是512M

常用命令
set <key> <value>   添加键值对(若key存在会进行覆盖)
get <key>       查看对应键值
append <key> <value>   将给定的<value>追加到原值的末尾
strlen <key>        获得值的长度
setnx <key> <value>    只有在key不存在时,才添加键值对

incr <key>          将key中存储的数字值增1,只能对数字值操作,如果为空,新增值为1
decr <key>           将key中存储的数字值减1,只能对数字值操作,如果为空,新增值为-1
incrby/decrby <key> <步长>   将key中存储的数字值增减,自定义步长

mset <key1> <value1> <key2> <value2> ...   同时设置一个或多个键值对(覆盖)
mget <key1> <key2> <key3> ...          同时获取一个或多个value
msetnx <key1> <value1> <key2> <value2> ...   同时设置一个或多个键值对(不可覆盖,且具有原子性,有一个失败则全都失败)

getrange <key> <起始位置> <结束位置>   获取指定key的值的范围内数据(索引从0开始)
setrange <key> <起始位置> <value>      用<value>覆写指定key从<起始位置>的值

setex <key> <过期时间> <value>    设置键值对的同时,设置过期时间,单位为秒
getset <key> <value>       以旧换新,设置新值的同时获得旧值

 

List

首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,即压缩列表;当数据量比较多的时候才会改成quicklist

Redis将链表和ziplist结合起来组成了quicklist,也就是将多个ziplist使用双向指针串起来使用,这样既满足了快速的插入删除性能,又不会出现太大的空间冗余

按照插入顺序排序
底层是一个双向列表

 

常用命令
lpush/rpush <key> <value1> <value2> ... 从左边/右边插入一个或多个值
lpop/rpop <key> 从左边/右边删除一个值(值没有了key也没了)

lrange <key> <start> <stop> 从左到右按照索引下标获得元素(0左边第一个,-1右边第一个)
lindex <key> <index> 按照索引下标获得元素(从左到右)
llen <key> 获得列表长度
linsert <key> before/after <value> <newvalue> 在<value>的前面/后面插入<newvalue> 的值
lrem <key> <n> <value> 从左到右删除n个<value>
lset <key> <index> <value> 将指定key中下标为<index>的值替换为<value>

 

Set

Set可以自动排重
底层是一个hash表

 

常用命令

sadd <key> <value1> <value2> ... 将一个或多个元素添加到集合key中,已经存在的元素将被忽略
smembers <key> 取出集合的所有值
sismember <key> <value> 判断集合<key>是否含有<value>值,0没有,1有
scard <key> 返回集合的元素个数
srem <key> <value1> <value2> ... 删除集合中的一个或多个元素
spop <key> 随机从集合中吐出一个值,会从集合中删除
srandmember <key> <n> 随机从集合中取出n个值,不会从集合中删除

smove <key1> <key2> <value> 把<key1>集合中的<value>移动到<key2>集合
sinter <key1> <key2> 返回两个集合的交集元素
sunion <key1> <key2> 返回两个集合的并集元素
sdiff <key1> <key2> 返回两个集合的差集元素

 

Hash

Hash类型对应的数据结构是两种:ziplist(压缩列表)、hashtable(哈希表)
当field-value长度较短且个数较少时使用ziplist,否则使用hashtable

Hash特别适合存储对象,类似Java中的Map<String, Object>

 

常用命令

hset <key> <field> <value> 给哈希表<key>的<field>键赋值为<value>(覆盖)
hget <key> <field> 从哈希表<key>的<field>取出value
hmset <key> <field1> <value1> <field2> <value2> ... 批量设置值
hexists <key> <field> 查看哈希表<key>中,给定域field是否存在
hkeys <key> 列出该hash集合的所有field
hvals <key> 列出该hash集合的所有value

hincrby <key> <field> <increment> 为哈希表<key>中的域<field>的值加上<increment>
hsetnx <key> <field> <value> 将哈希表<key>中的域<field>的值设为<value>(不可覆盖)

 

Zset

Zset的底层使用了两个数据结构:

  • hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到对应的score值
  • 跳跃表,跳跃表的目的是给元素value排序,根据score的范围获取元素的列表

有序集合和普通集合非常相似,是一个没有重复元素的集合
有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但评分(score)可以是重复的

 

常用命令

zadd <key> <score1> <value2> <score2> <value2> ... 将一个或多个元素及其score值加入到有序集合中
zrange <key> <start> <stop> [withscores] 返回有序集合<key>中下标在<start><stop>之间的元素,带WITHSCORES可以返回元素和评分(0分数最小,-1分数最大)
zrangebyscore <key> <min> <max> [withscores] 返回有序集合<key>中score值介于<min>和<max>之间的成员(包括等于min或max的成员),按score值从小到大次序排列
zrevrangebyscore <key> <max> <min> [withscores] 同上,改为从大到小次序排列
zincrby <key> <increment> <value> 为元素的score加上<increment>
zrem <key> <value> 删除有序集合指定<value>元素
zcount <key> <min> <max> 统计有序集合score值介于<min><max>之间的的元素个数
zrank <key> <value> 返回该值在集合中的排名,从0开始

 

Redis新数据类型

Bitmaps

Bitmaps本身并不是一种数据类型,实际上它就是字符串,但它可以对字符串的位进行操作
Bitmaps单独提供了一套命令,可以把Bitmaps想象成为一个以位为单位的数组,数组的每个单元只能存储0和1,数组的下标叫做偏移量

 

setbit <key> <offset> <value> 设置Bitmaps中<offset>偏移量的值(0或1)
getbit <key> <offset> 获取Bitmaps中<offset>偏移量的值

bitcount <key> 统计字符串中比特值为1的数量
bitcount <key> <start> <end> 统计字符串从<start>字节到<end>字节中比特值为1的数量

bitop and/or/not/xor <destinationKey> <key1> <key2> ... 做多个Bitmaps的and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在<destinationKey>中
每个独立用户是否访问过网站存放在Bitmaps中,将访问的用户记作1,没有访问的用户记作0,用偏移量作为用户的id
将key设置为类似 users:20210509 格式可以记录每天访问网站的记录

 

HyperLogLog

HyperLogLog是用来做基数统计的算法,优点是输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的、并且是很小的
每个HyperLogLog键只需花费12KB内存
但是HyperLogLog只会根据输入元素来计算基数,而不会存储输入元素本身
基数不包含重复元素,基数是不重复元素的个数

 

常用命令

pfadd <key> <element1> <element2> ...   添加指定元素到HyperLogLog中
pfcount <key1> <keye2> ...         计算近似基数,可以计算多个近似基数
pfmerge <destinationKey> <key1> <key2> ...   将一个或多个HyperLogLog合并后的结果存储在<destinationKey>中,比如每月活跃用户可以使用每天的活跃用户来合并计算得到

 

Geospatial

该类型,就是元素的二维坐标,在地图上就是经纬度

 

常用命令

geoadd <key> <longitude> <latitude> <member> 添加地理位置,可以同时添加多个(经度,纬度,名称)
geopos <key> <member> 获取指定地区的坐标值
geodist <key> <member1> <member2> [m|km|ft|mi] 获取两个位置之间的直线距离,默认值米m、千米km、英里mi、英尺ft
georadius <key> <longitude> <latitude> <radius> [m|km|ft|mi] 以给定的经纬度为中心,找出某一半径内的元素

Redis的发布和订阅

发布者(pub)发送消息,订阅者(sub)接收消息
Redis客户端可以订阅任意数量的频道

 

打开一个客户端订阅 mychannel

subscribe mychannel

  

打开另一个客户端,给 mychannel 发布消息 hello

publish mychannel hello

  

此时打开第一个客户端即可看到发送的消息

 

推荐阅读