这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
NoSQL概念
NoSQL,指非关系型数据库,不支持SQL语法。关系型数据库,每次操作关系型数据库时都是I/O操作,I/O操作是主要影响程序执行性能原因之一,连接数据库关闭数据库都是消耗性能的过程。尽量减少对数据库的操作,能够明显的提升程序运行效率。
常见NoSQL数据库
Memcached :键值对,内存型数据库,所有数据都在内存中。
Redis:和Memcached类似,还具备持久化能力。
HBase:以列作为存储。
MongoDB:以Document做存储。
NoSQL分类
键值(Key-Value)存储数据库
键值存储数据库。用key-value的方式来存储数据,其中key和value可以是简单的数据,也可以是复杂的对象。key作为唯一的标识符,优点是查询速度比sql快多了,但是缺点也很明显,它无法像关系型数据库一样自由使用条件过滤(比如:where条件语句),如果你不知道去哪里找数据,就会从头遍历所有的数据,这就会消耗大量计算。
Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB
列存储数据库
相对于行式存储的数据库(Oracle、MySQL、SQL Server 等数据库都是采用的行式存储),列式数据库是将数据按照列存储到数据库中,这个做可以大量降低系统的I/O,适合于分布式文件系统,不足在于功能相对有限。
列式数据库将数据按照列进行存储,因为每列的数据格式是相同的,在存储过程时,可以使用有效的压缩算法进行压缩存储,压缩后的数据容量变小,所以降低了I/O
Cassandra, HBase, Riak
文档型数据库
文档型数据库用来管理文档,在数据库中文档作为处理信息的基本单位,一个文档就相当于一条记录
CouchDB, MongoDb. 国内也有文档型数据库SequoiaDB,已经开源
图形(Graph)数据库
利用了图这种数据结构存储了实体(对象)之间的关系。最典型的例子就是社交网络中人与人的关系,数据模型主要是以节点和边(关系)来实现,特点在于能高效地解决复杂的关系问题。
如:Neo4J, InfoGrid, Infinite Graph。
Redis简介
Redis是使用C语言进行编写的
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis以slot(槽)作为数据存储单元,每个槽中可以存储N多个键值对。Redis中固定具有16384。理论上可以实现一个槽是一个Redis。每个向Redis存储数据的key都会进行crc16算法得出一个值后对16384取余就是这个key存放的slot位置
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
Redis 优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
Redis数据类型(面试)
Redis中数据是key-value形式。不同类型Value是有不同的命令进行操作。key为字符串类型,value常用类型:
-
String 字符串
-
Hash 哈希表
-
List 列表
-
Set 集合
-
Sorted Set 有序集合(zSet)
Redis命令相关手册有很多,下面为其中比较好用的两个
Redis持久化策略(面试问题)
Redis不仅仅是一个内存型数据库,还具备持久化能力。
一共包含两种持久化策略:RDB 和 AOF
RDB(Redis DataBase)
默认情况下,Redis使用RDB模式,该模式在指定的时间间隔内生成数据快照(snapshot),默认保存到dump.rdb文件中。当redis重启后会自动加载dump.rdb文件中内容到内存中。
可以使用SAVE(同步)或BGSAVE(异步)手动保存数据
save 内存生存快照,将快照保存到磁盘中,对外停止提供服务
bgsave 在保存快照到磁盘中时,也可以对外提供服务,在保存快照时,会在内存中额外生成快照区用于保存数据,保存快照区,数据区,是分离的。内存中快照区在写入磁盘的过程,不影响内存的数据变更。
可以设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令,可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE命令。 例如:
save 900 1
save 300 10
save 60 10000
那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行。计时单位是必须要执行的时间,
save 900 1 ,每900秒检测一次。在并发量越高的项目中Redis的时间参数设置的值要越小。 服务器在900秒之内,对数据库进行了至少1次修改 ,生成快照 服务器在300秒之内,对数据库进行了至少10次修改 ,生成快照 服务器在60秒之内,对数据库进行了至少10000次修改,生成快照
优点
rdb文件是一个紧凑文件,直接使用rdb文件就可以还原数据。
数据保存会由一个子进程进行保存,不影响父进程做其他事情。
恢复数据的效率要高于aof
缺点
每次保存点之间导致redis不可意料的关闭,可能会丢失数据。
由于每次保存数据都需要fork()子进程,在数据量比较大时可能会比较耗费性能。
AOF(AppendOnly File)
用文件记录命令流程,每1秒中追加这一秒执行的命令
AOF默认是关闭的 appendor no ,要在配置文件redis.conf中开启AOF。Redis支持AOF和RDB同时生效,如果同时存在,AOF优先级高于RDB(Redis重新启动时会使用AOF进行数据恢复)
AOF原理:监听执行的命令,如果发现执行了修改数据的操作,同时直接同步到数据库文件中,同时会把命令记录到日志中。即使突然出现问题,由于日志文件中已经记录命令,下一次启动时也可以按照日志进行恢复数据,由于内存数据和硬盘数据实时同步,即使出现意外情况也需要担心。
优点
相对RDB数据更加安全。
缺点
相同数据集AOF要大于RDB
相对RDB可能会慢一些
Redis主从复制
Redis支持集群功能。为了保证单一节点可用性,redis支持主从复制功能。每个节点有N个复制品(replica),其中一个复制品是主(master),另外N-1个复制品是从(Slave),也就是说Redis支持一主多从。
一个主可有多个从,而一个从又可以看成主,它还可以有多个从。
一个主提供服务,多个从进行备份,防止数据丢失。
主从优点
增加单一节点的健壮性,从而提升整个集群的稳定性。(Redis中当超过1/2节点不可用时,整个集群不可用)
从节点可以对主节点数据备份,提升容灾能力。
读写分离。在redis主从中,主节点一般用作写(具备读的能力),从节点只能读,利用这个特性实现读写分离,写用主,读用从
哨兵(Sentinel)
在redis主从模型是只有主(Master)具备写的能力,而从(Slave)只能读。如果主宕机,整个节点不具备写能力。但是如果这时让一个从变成主,整个节点就可以继续工作。即使之前的主恢复过来也当做这个节点的从即可。
Redis的哨兵就是帮助监控整个节点的,当主节点宕机等情况下,帮助重新选取主。
Redis中哨兵支持单哨兵和多哨兵。单哨兵是只要这个哨兵发现master宕机了,就直接选取另一个master。而多哨兵是根据我们设定,达到一定数量哨兵认为master宕机后才会进行重新选取主
一主多从搭建
-
关闭redis
-
新建目录
mkdir /usr/local/replica
-
将redis 复制到新建的目录
cp -r /usr/local/redis/bin /usr/local/replica/master
-
修改从的配置文件
master配置
vim /usr/local/replica/master/redis.conf
prot 6001
slave1配置
vim /usr/local/replica/slave1/redis.conf
prot 6001
replicaof 192.167.1.179 6001
slave2配置
vim /usr/local/replica/slave2/redis.conf
prot 6003
replicaof 192.167.1.179 6001
- 启动Redis
Redis 命令
通用操作
keys : 显示redis中的key
根据表达式,显示redis中的key。
返回值: redis中的key列表
语法: keys 表达式 [如: keys * ]
exists : 判断key是否存在
判断key是否存在。
语法:exists key名称
返回值:存在返回数字,不存在返回0
ttl : 查看key的剩余过期时间
查看key的剩余过期时间
语法:ttl key
返回值:返回剩余时间,如果不过期返回-1
expire : 设置key的过期时间
设置key的过期时间,单位秒
语法:expire key 秒数
返回值:成功返回1,失败返回0
persist : 删除key的有效时长
删除key的有效时长
语法: persist key
返回值:返回删除有效时长的key的个数。
del : 根据key删除
根据key删除键值对。
返回值:被删除key的数量
语法:del key
flushall:清空redis中所有键值对
清空redis中所有键值对
语法: flushall
dbsize:键值对数量数
返回redis中数据库键值对数量数
语法: dbsize
select:切换数据库
切换使用的数据库,Redis默认安装时有16个数据库,编号索引是0~15。默认链接redis使用的是0号数据库,可以自主切换数据库。
语法: select 数据库索引
字符串值(String)
set : 设置指定key的值
如果key不存在是新增效果,如果key存在是修改效果。键值对是永久存在的。
语法:set key value
返回值:成功OK
get : 获取指定key的值
语法:get key
返回值:key的值。不存在返回nil
setnx : 当且仅当key不存在时才新增
key不存在时,增加,key存在时无法修改。
语法:setnx key value
返回值:不存在时返回1,存在返回0
setex : 设置key的存活时间,并修改值
无论是否存在指定key都能新增,如果存在key覆盖旧值。同时必须指定过期时间。
语法:setex key seconds value
返回值:OK
mset:批量添加数据
mget:批量查询数据
哈希表(Hash)
Hash类型的值中包含多组field value
hset:添加
给key中field设置值。
语法:hset key field value
返回值:成功1,失败0
hget:查询
获取key中某个field的值
语法:hget key field
返回值:返回field的内容
hmset:给key中多个filed设置值
给key中多个filed设置值
语法:hmset key field value field value ...
返回值:成功OK
hmget: 获取key中多个field的值
一次获取key中多个field的值
语法:hmget key field field
返回值:value列表
hkeys:查询key中所有的field
获取key中所有的field名称
语法:hkeys key
返回值: field名称列表
hvals:查询key中所有field的值
获取key中所有field的值
语法:hvals key
返回值:value列表
hgetall:获取Key所有field和value
获取所有field和value
语法:hgetall key
返回值:field和value交替显示列表
hdel:删除key中多个field
删除key中任意个field
语法:hdel key field field ...
返回值:成功删除field的数量,当key对应的所有field全部删除,自动删除key。
列表(List)
rpush:末尾插值
向列表末尾中插入一个或多个值
语法;rpush key value value
返回值:列表长度
lrange:查询
返回列表中指定区间内的值。可以使用-1代表列表末尾
list中下标有两种计数方式,头->尾 0,1,2,3 .... 尾->头 -1,-2,-3 ...
语法:lrange list 0 -1
返回值:查询到的值
lpush:插值
将一个或多个值插入到列表前面
语法:lpush key value value
返回值:列表长度
llen:获取列表长度
获取列表长度
语法:llen key
返回值:列表长度
lrem:删除列表中元素
删除列表中元素。count为正数表示从左往右删除的数量。负数从右往左删除的数量。
语法:lrem key count value
返回值:删除数量。
集合(Set)
set和java中集合一样。
sadd:添加
向集合中添加内容。不允许重复。
语法:sadd key value value value
返回值:成功新增元素个数
scard:查询
返回集合元素数量
语法:scard key
返回值:集合长度
smembers:查看set内容
查看集合中元素内容
语法:smembers key
返回值:集合中元素
有序集合(Sorted Set)
有序集合中每个value都有一个分数(score),根据分数进行排序。
zadd:添加有序set
向有序集合中添加数据
语法:zadd key score value score value
返回值:长度
zrange:查看有序set
返回区间内容,withscores表示带有分数
语法:zrange key 区间 [withscores]
返回值:值列表
zcard:查看有序set元素数量
返回集合中元素数量
语法: zcard key
zrem:删除有序set元素
删除集合中元素
语法: zrem key value1 value2 [...]