NoSQL
not only SQL
常见的Nosql
Redis memcha Hbase MongoDB
redis
remote dictionary sever
特征
key-value 内部采用单线程 性能高 多数据类型存储(String、list、hash、set、sorted_set) 支持持久化
应用
加速热点信息的查询 任务队列 信息即时查询 时效性的东西 分布式数据共享
五种数据类型
字符类型String
字符串或者是数值,可以设置其过期时间
命令 | 作用 |
---|---|
set key value | 添加一个key |
get key | 查询信息,如果不存在的话返回nil |
del key | 删除(删除成功返回1,删除失败返回0) |
mset key1 value1 key2 value2 | 存储多个数据 |
mget key1 key2 | 获取多个值 |
strlen key | 返回字符串长度 |
append key 追加的内容 | 给key追加值,如果不存在直接新建key |
incr key | 让字符数值增加1,例如2变为3,返回值是value |
decr key | 让字符数值减少1,例如3变为2,返回值是value |
incrby key num | 让value值增加num(num为整数),返回值是value |
decrby key num | 让value值减少num,返回值是value |
incrbyfloat key num | 让value值增加num(num为小数),返回值是value |
decrbyfloat key num | 让value值减少num(num为小数),返回值是value |
setex key seconds value | 让一个值存在多少秒数,时间到了就没了 |
psetex key milliseconds value | 让一个值存在多少毫秒 |
PS:
①使用数值操作,如果不能转换为数字或者范围超出将报错。其最大值范围-9223372036854775808到9,223,372,036,854,775,807,即是-2的63次方到2的63次方-1
②string的最大数据是512MB
哈希hash
hash可被认为是key的值是一个字典,通过指定key field才能找到具体的值。
命令 | 作用 |
---|---|
hset key field vaue | 给key新增一个field其值为value |
hget key field | 获取key值中field的值 |
hgetall key | 获取key中所有东西 |
hdel key field1 field2 | 删除key中的field1…. |
hlen key | key有的field数量 |
hexists key field | 查看key中是否存在field |
hkeys key | 查看key下的所有field |
hvals key | 查看key下的所有value |
hincrby key filed num | 让key中的filed增加num |
hincrbyfloat key filed num | 让key中的filed增加num(小数) |
hmset key field1 value1 … | 设置多个值 |
hdel key field | 删除key中field |
hsetnx key field value | 如果存在不变,如果不存在添加 |
PS:
①value中只能是字符串/数值类型。
②hash中的存储类似于对象,但是不能滥用。
③hash不能设置过期时间。
列表list
存储多个数据,底层使用的数据结构为双向列表。使用的插入方法是头插法。
例如:如图,从左遍历是b a ,插入c ,因为是头插,所以成了cba (从左边遍历)
命令 | 作用 |
---|---|
lpush key value1 value2 | 左插入list |
rpush key value1 value2 | 将数据右插入list |
lrange key start end | 查看start到end的元素(end可以为负数,但是start不能为负数) |
lindex key index | 查看位置为index的元素 |
llen key | 查看key的长度 |
lpop key | 获取并且移除左边的数据 |
rpop key | 获取并且移除右边的数据 |
blpop key time | 在一定时间内左边取出数据且移除 |
brpop key time | 在一定时间内右边取出数据且移除 |
lrem key n value | 移除列表里的值value,并且移除n个value |
集合set
存储大量数据,提供高效率查询,数据不允许重复。可以用于去重 。
命令 | 作用 |
---|---|
sadd key value1 value2 | 增加元素 |
smembers key | 查看key中所有元素 |
srem key value | 移除某个元素 |
scard key | 获取集合元素的总数量 |
sismembers key member | 查看member是否在集合中 |
srandmember key count | 随机取集合中的一个值,不在元素中删除 |
spop kye | 随机获取集合中的某个数据且移除 |
sinter set1 set2… | 求交集 |
sunion set1 set2…. | 求并集 |
sdiff set1 set2 | 求差集 |
sinterstore set1 set2 set3 | 将set2与set3的交集存到set1中 |
sunionstore set1 set2 set3 | 将set2与set3的并集存到set1中 |
sdiffstore set1 set2 set3 | 将set2与set3的差集存到set1中 |
smove set1 set2 member | 将set1中的member移到set2中,s1中会去除 |
排序集合 sorted_set
key member score,某个班级里某个同学有一个分数,通过分数排名。
命令 | 作用 |
---|---|
zadd key score member score1 member1 | 添加数据 |
zrange key start stop (withscores) | 从start看到stop,选择是否看到score(由小到大排的),不使用withscore返回的menber的值 使用withscores返回的数据为member1 score1 member2 score1 2 |
zrevrange key start stop (withscores) | 从start看到stop,选择是否看到score(由大到小排的) |
zrem key member | 移除数据 |
zrangebyscore key min max (withscores limit start end) | 查看min到max之间的数据,可以使用limit限制数量。从小到大。 |
zrevrangebyscore key max min (withscores limit start end) | 查看min到max之间的数据,可以使用limit限制数量, 从大到小。 |
zremrangebyrank key start stop | 按索引删除,start到stop的都删除(两端的都删除) |
zremrangebyscore key min max | 按score删除,删除从min到max的数据 |
zcard key | 查看多少数据 |
zconut key min max | 查看范围在min到max中的数据总数 |
zinterstore st1 num st2 st3 st4 (ZINTERSTORE destination numkeys key [key ...][WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX) | 交集,指定num个st(后面写的数量需与num一致),将这些个集合里都公共的东西的score加起来,然后存在st1中,还可以求平均最大最小,以及设置权重。 |
zunionstore st1 num st2 st3 st4 | 并集,指定num个st(后面写的数量需与num一致),将这些个集合里都公共的东西的score加起来,然后存在st1中,还可以求平均最大最小,以及设置权重。 |
zrank key member | 查看member的索引,从小到大 |
zrevrank key member | 查看member的索引,从大到小 |
zscore key member | 查看member的score |
zincrby key num member | 将key中的member加num |
PS:
①如果score使用整数,其范围是2的64位。
②score为小数的时候,是双精度的double类型,进行加减的时候会造成精度丢失等。
参考:
https://blog.csdn.net/qq_27215113/article/details/100663914
通用命令
key相关
命令 | 作用 |
---|---|
del key | 删除key |
exists key | 查看key是否存在 |
type key | 查看key的类型 |
expire key seconds | 为key设置有效期,秒数 |
pexpire key milliseconds | 为key设置有效期,毫秒数 |
ttl key | 获取key的有效时间(如果key是永久的返回-1,如果key是已经失效,返回-2) |
persist key | 将key转为永久化的 |
db相关
命令 | 作用 |
---|---|
select index | 选择数据库 |
quit | 退出 |
ping | 查看是否建立连接 |
move key db | 把当前的数据库的key移动到db中,db中不能存在相同的key |
dbsize | 查看当前数据库的key的多少 |
flushdb | 清除当前数据库的key |
flushall | 删除数据库所有数据 |
持久化
save 前台保存 bgsave 后台保存 利用永久性存储介质,在特定时间里将保存的数据恢复回去。 RDB存储的数据是存在data里面的 xxxx.rdb文件,里面存储的持久化的数据。
方式 | save | bgsave |
---|---|---|
读写 | 同步 | 异步 |
阻塞 | 是 | 否 |
额外消耗内存 | 否 | 是 |
是否启新进程 | 否 | 是 |
RDB
RDB为存取某个时间段的快照。
配置文件相关
命令 | 作用 |
---|---|
rdbchecksum yes | 从版本RDB版本5开始,一个CRC64的校验就被放在了文件末尾.这会让格式更加耐攻击,但是当存储或者加载rbd文件的时候会有一个10%左右的性能下降,所以,为了达到性能的最大化,你可以关掉这个配置项。没有校验的RDB文件会有一个0校验位,来告诉加载代码跳过校验检查 |
rdbcompression yes | 是否在导出.rdb数据库文件的时候采用LZF压缩字符串和对象,默认情况下总是设置成‘yes’,他看起来是一把双刃剑.如果你想在存储的子进程中节省一些CPU就设置成'no',但是这样如果你的key/value是可压缩的,你得到的数据接就会很大。 |
dbfilename xxx.rdb | 存储数据的文件名称 |
stop-writes-on-bgsave-error yes | 在默认情况下,如果RDB快照持久化操作被激活(至少一个条件被激活)并且持久化操作失败,Redis则会停止接受更新操作.这样会让用户了解到数据没有被正确的存储到磁盘上。否则没人会注意到这个问题,可能会造成灾难,#如果后台存储(持久化)操作进程再次工作,Redis会自动允许更新操作.然而,如果你已经恰当的配置了对Redis服务器的监视和备份,你也许想关掉这项功能,如此一来即使后台保存操作出错,redis也仍然可以继续像平常一样工作。 |
dir ./data | 数据文件存储位置 |
save second nums | 当限定时间内key的数量变化达到了一定数量就进行持久化 |
流程细说
当条件满足,redis需要执行RDB的时候,服务器会执行以下操作:
- redis调用系统函数fork() ,创建一个子进程。
2.子进程将数据集写入到一个临时 RDB 文件中。
3.当子进程完成对临时RDB文件的写入时,redis 用新的临时RDB 文件替换原来的RDB 文件,并删除旧 RDB 文件。
在执行fork的时候操作系统(类Unix操作系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行一个写命令 ),操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的RDB文件存储的是执行fork那一刻的内存数据。
Redis在进行快照的过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的。这使得我们可以通过定时备份RDB文件来实 现Redis数据库备份。RDB文件是经过压缩(可以配置rdbcompression参数以禁用压缩节省CPU占用)的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。
除了自动快照,还可以手动发送SAVE或BGSAVE命令让Redis执行快照,两个命令的区别在于,前者是由主进程进行快照操作,会阻塞住其他请求,后者会通过fork子进程进行快照操作。
优点与缺点
优点
1.RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。
2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
缺点
1.如果你需要尽量避免在服务器故障时丢失数据,那么RDB 不适合你。 虽然Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。
2.每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。
3.redis多版本的rbd文件可能不一致,同一文件在不同版本可能不适用。
通过RDB方式实现持久化,一旦Redis异常退出,就会丢失最后一次快照以后更改的所有数据。 参考: https://blog.csdn.net/aitangyong/article/details/52045251
AOF
append only file,将数据的变化操作记录到文件中,重启之后执行这些数据变化,以保持与之前的数据一致。
相关配置
命令 | 作用 |
---|---|
appendonly no | 是否开启aof |
appendfilename "appendonly.aof" | 数据存储文件名 |
appendfsync no | 配置写数据策略有:always 每次数据变化都记录,性能低.exerysec每秒 将缓冲区指令放到aof文件中,性能较高.no 有系统控制,整体自己不可控。 |
auto-aof-rewrite-percentage | 触发自动重写的最低文件体积(小于64mb不自动重写) |
aof-use-rdb-preamble yes | 开启混合持久化 |
流程详解
在使用AOF如果频繁修改一个key的value,只有最后的value才是有效的,中间的修改可以认为是无用的,,但是无用操作都会写到AOF。在AOF中有一个重写机制,会将这些中间数据删除,只记录最后的,因为重写机制会使恢复数据更快。其重写机制如下: ①进程已超时的数据不再写入文件中。 ②中间数据不写入,只写入最终的数据。 ③对同一个数据的多个写操作,将其和并为一条指令,但是为了防止缓冲区溢出,对list,set,hash等每条指令最多写入64个元素。
优点与缺点
优点
①AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。 ②AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 工具也很容易修正 AOF 文件。 ③AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。
缺点
①对于具有相同数据的的Redis,AOF文件通常会比RDF文件体积更大。
②虽然AOF提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在Redis的负载较高时,RDB比AOF具好更好的性能保证。 ③RDB使用快照的形式来持久化整个Redis数据,而AOF只是将每次执行的命令追加到AOF文件中,因此从理论上说RDB比AOF方式更健壮。官方文档也指出,AOF的确也存在一些BUG,这些BUG在RDB没有存在
RDB和AOF对比
方式 | RDB | AOF |
---|---|---|
占用存储 | 小 | 大 |
存储速度 | 慢 | 快 |
恢复速度 | 快 | 慢 |
数据安全 | 会丢失数据 | 根据策略而定 |
资源消耗 | 多 | 少 |
启动优先级 | 低 | 高 |
事务
命令
命令 | 作用 |
---|---|
mutil | 开启事务,开启事务后直到关闭事务这期间执行的操作会放到事务中。 |
exec | 执行事务 |
discard | 取消事务 |
细节
①事务中存在错误 格式输入错误的命令,例如st key value:事务中的所有命令均不会被执行,
②事务中存在 命令格式正确但是无法正确执行的操作,例如将string认为是list,进行list相关的操作。事务中的正确指令将会执行,但是那些无法正确执行的操作,将不会执行。
删除策略
redis中存在一些过期的数据, 其目标是:在使用内存占用和CPU占用的之间找一个平衡,不让redis性能降低.
定时删除
创建一个定时器,当存在key设置了过期时间,且达到了过期时间,定时器就会执行相关的删除操作。(用时间换空间)
优缺点
优点
占用内存小,到时间就会删除,不会浪费内存。
缺点
CPU的压力会很大,无论CPU的负载多高,都会占用内存,会影响Redis的响应时间和指令的吞吐量。
惰性删除
等数据到达过期时间后,等下次访问该数据的时候才进行相关的删除操作。在这个所谓的下次访问数据的时候,当数据没有过期就会被正取返回,反之就会将数据进行删除。
优缺点
优点
节约CPU的性能,发现删除的时候才会进行删除。
缺点
对内存占用较大,可能出现过期的key长时间占用内存。
定期删除
Redis 默认会每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。 从过期字典中随机 20 个 key; 删除这 20 个 key 中已经过期的 key; 如果过期的 key 比率超过 1/4,那就重复步骤 1;
特点
特点1:CPU性能占用设置有峰值,检测频度可自定义设置 §特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理 总结:周期性抽查存储空间 (随机抽查,重点抽查) redis删除策略是 惰性删除+定期删除
逐出算法
Redis使用内存存储数据,在执行每一一个命令前, 会调用freeMemorylfNeeded()检测内存是否充足。 如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。 清理数据的策略称为逐出算法。 注意:逐出数据的过程不是100%能够清理出足够的可使用的内存空间,如果不成功则反复执行。当对所有数据尝试完毕后,如果不能达到内存清理的要求,将出现错误信息。
相关配置
配置 | 释义 |
---|---|
maxmemory | 最大可用内存,占物理内存的大小,默认为全用,通常设置50%以上。 |
maxmemory-samples | 每次选取待删除的数据的个数 |
maxmemory-policy | 达到最大内存后,对被挑选的数据的删除算法,逐出算法的策略 |
逐出算法
检测易失数据
volatile-lru:挑选最近最少使用的数据淘汰
volatile-lfu:挑选最近使用次数最少的数据淘汰
volatile-ttl:挑选将要过期的数据淘汰
volatile-random:任意选择数据淘汰
检测全库数据
allkeys-lru:挑选最近最少使用的数据淘汰
allkeys-lfu:挑选最近使用次数最少的数据淘汰
allkeys-random:任意选择数据淘汰
放弃逐出
no-enviction(驱逐):禁止驱逐数据(redis4.0中默认策略),会引发错误OOM(Out Of Memory)