redis
2023-01-10 11:42:15 2 举报
AI智能生成
登录查看完整内容
redis总结
作者其他创作
大纲/内容
字符串(strings)
散列(hashes)
列表(lists)
集合(sets)
有序集合(sorted sets)
通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态
位图(bitmaps)
计算重复的值,确定存储的数量,只提供基数的运算,不提供返回的功能
基数(hyperloglogs)
可以推算出地理位置,两地之间的距离
地理空间(geospatial)
数据类型
将key设定为指定字符串值,如果key已经保存了一个值,将会覆盖原来的值,并且忽略原来类型,当set执行成功后,之前设置的过期时间都会失效
SET PX 设置键key的过期时间,单位时毫秒
SET NX 只有键key不存在的时候才会设置key的值 eg:seg mykey myvalue2 NX 如果已经存在值,则不会生效
SET XX 只有键key存在的时候才会设置key的值 eg:seg mykey myvalue2 NX 如果不存在值,则不会生效
SET
获取key的值,如果value不是string,则返回错误,get只处理string类型的的value
GET
字符串操作,执行原子加1,如果指定的key不存在,那么在执行incr操作之前,会先将它的值设定为0
执行这个操作的时候,key对应存储的字符串被解析为10进制的64位有符号整型数据
INCR
整数原子减一
DECR
bit要么被设置,要么被清空,这个由value(只能是0或者1)来决定。当key不存在的时候,就创建一个新的字符串value
eg:SETBIT mykey 7 1
SETBIT
返回key对应的string在offset处的bit值 当offset超出了字符串长度的时候,这个字符串就被假定为由0比特填充的连续空间。当key不存在的时候,它就认为是一个空字符串,所以offset总是超出范围,然后value也被认为是由0比特填充的连续空间
eg:GETBIT mykey 7
GETBIT
strings
设置 key 指定的哈希集中指定字段的值。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段在哈希集中存在,它将被重写
返回结果:1 代表是一个新的字段,0:代表原来的map里面已经存在,覆盖了原来值
eg:HSET myhash field1 \"Hello\"
HSET
span style=\
eg:HSET myhash field1
HGET
从 key 指定的哈希集中移除指定的域。在哈希集中不存在的域将被忽略。如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回0
HDEL
返回 key 指定的哈希集包含的字段的数量
HLEN
返回 key 指定的哈希集中所有字段的值
HVALS
hashs
把 value 插入存于 key 的列表中在基准值 pivot 的前面或后面。当 key 不存在时,这个list会被看作是空list,任何操作都不会发生。当 key 存在,但保存的不是一个list的时候,会返回error。
eg:RPUSH mylist \"Hello\"RPUSH mylist \"World\"LINSERT mylist BEFORE \"World\" \"There\"
LINSERT
将所有指定的值插入到存于 key 的列表的头部。如果 key 不存在,那么在进行 push 操作前会创建一个空列表。 如果 key 对应的值不是一个 list 的话,那么会返回一个错误
EG:LPUSH mylist \"world\"
LPUSH
向存于 key 的列表的尾部插入所有指定的值。如果 key 不存在,那么会创建一个空的列表然后再进行 push 操作。 当 key 保存的不是一个列表,那么会返回一个错误
RPUSH
返回存储在 key 的列表里指定范围内的元素。 start 和 end 偏移量都是基于0的下标,即list的第一个元素下标是0(list的表头),第二个元素下标是1,以此类推。偏移量也可以是负数,表示偏移量是从list尾部开始计数。 例如, -1 表示列表的最后一个元素,-2 是倒数第二个,以此类推
eg:LRANGE mylist 0 0
LRANGE
只有当 key 已经存在并且存着一个 list 的时候,在这个 key 下面的 list 的头部插入 value。 与 LPUSH 相反,当 key 不存在的时候不会进行任何操作
LPUSHX
RPUSHX
移除并且返回 key 对应的 list 的第一个元素
eg:RPOP mylist
LPOP
移除并返回存于 key 的 list 的最后一个元素
RPOP
EG:RPOPLPUSH mylist myotherlist\"three\"
RPOPLPUSH
返回列表里的元素的索引 index 存储在 key 里面。 下标是从0开始索引的,所以 0 是表示第一个元素, 1 表示第二个元素,并以此类推。 负数索引用于指定从列表尾部开始索引的元素。在这种方法下,-1 表示最后一个元素,-2 表示倒数第二个元素,并以此往前推。当 key 位置的值不是一个列表的时候,会返回一个error
EG:LINDEX mylist 0
LINDEX
设置 index 位置的list元素的值为 value当index超出范围时会返回一个error
EG:LSET mylist 0 \"four\"
LSET
返回存储在 key 里的list的长度。 如果 key 不存在,那么就被看作是空list,并且返回长度为 0。 当存储在 key 里的值不是一个list的话,会返回error
LLEN
Lists
eg:SADD myset \"Hello\"
SADD
返回key集合所有的元素.该命令的作用与使用一个参数的SINTER 命令作用相同.
SMEMBERS
返回指定所有的集合的成员的交集
SINTER
返回成员 member 是否是存储的集合 key的成员
SISMEMBER
从存储在key的集合中移除并返回一个或多个随机元素。此操作与SRANDMEMBER类似,它从一个集合中返回一个或多个随机元素,但不删除元素
SPOP
SREM
SETS
数据结构:有序集合的分数使用双精度64位浮点数
将所有指定成员添加到键为key有序集合(sorted set)里面。 添加时可以指定多个分数/成员(score/member)对。 如果指定添加的成员已经是有序集合里面的成员,则会更新改成员的分数(scrore)并更新到正确的排序位置。如果key不存在,将会创建一个新的有序集合(sorted set)并将分数/成员(score/member)对添加到有序集合,就像原来存在一个空的有序集合一样。如果key存在,但是类型不是有序集合,将会返回一个错误应答
ul style=\
参数
ZADD
返回key的有序集元素个数
ZCARD
返回的是从有序集合中删除的成员个数,不包括不存在的成员
ZREM
sorted sets
常用命令
SDS 所保存的字符串长度。这样获取字符串长度的时候,只需要返回这个变量值就行,时间复杂度只需要 O(1)
len
分配给字符数组的空间长度。这样在修改字符串的时候,可以通过 alloc - len 计算 出剩余的空间大小,然后用来判断空间是否满足修改需求,如果不满足的话,就会自动将 SDS 的空间扩展至执行修改所需的大小,然后才执行实际的修改操作,所以使用 SDS 既不需要手动修改 SDS 的空间大小,也不会出现前面所说的缓冲区益处的问题
alloc
SDS 类型,用来表示不同类型的 SDS。一共设计了 5 种类型,分别是 sdshdr5、sdshdr8、sdshdr16、sdshdr32 和 sdshdr64,后面在说明区别之处
flags
字节数组,用来保存实际数据。不需要用 “\\0” 字符来标识字符串结尾了,而是直接将其作为二进制数据处理,可以用来保存图片等二进制数据。它即可以保存文本数据,也可以保存二进制数据,所以叫字节数组会更好点
buf[]
具有动态增加空间的能力,可以自动扩容
SDS(简单动态字符串)
set数据类型的底层实现数据结构
INT SET
hash-max-ziplist-entries 512 // ziplist 元素个数超过 512 ,将改为hashtable编码
hash-max-ziplist-value 64 // 单个元素大小超过 64 byte时,将改为hashtable编码
DICT
是由一系列特殊编码的连续内存块组成的顺序存储结构,类似于数组,ziplist在内存中是连续存储的,但是不同于数组,为了节省内存 ziplist的每个元素所占的内存大小可以不同(数组中叫元素,ziplist叫节点entry),每个节点可以用来存储一个整数或者一个字符串
是List、Zset、Hash数据类型的底层数据结构之一
ziplist的长度(单位: 字节),是一个32位无符号整数,记录整个压缩列表占用对内存字节数
zlbytes
记录压缩列表「尾部」节点距离起始地址由多少字节,也就是列表尾的偏移量;,反向遍历ziplist或者pop尾部节点的时候有用
zltail
ziplist的节点(entry)个数 entry: 节点 zlend: 值为0xFF,用于标记ziplist的结尾
zllen
ZIP LIST
在Redis3.2.0版本的时候引入了quicklist链表结构,结合了linkedlist和ziplist的优势
QUICK LIST
是Zset的底层数据结构,有着高性能的查找排序能力
SKIP LIST
Redis List数据类型底层就是基于链表来实现
LINKED LIST
Redis内部每一种数据类型都是对象化的,也就是我们所说的5种数据类型其实内部都会对应到Redis Object对象,然后再由Redis Object来包装具体的存储数据结构和编码
REDIS OBJECT
数据结构原理
对象内存,是Redis内存占用最大的一块,存储着用户所有的数据。Redis所有的数据都采用key-value格式,每次创建键值对时,至少创建两个类型对象:key对象和value对象。key对象都是字符串,value对象包含五种数据结构类型。所以,对象内存消耗可以简单理解为sizeof(keys)+sizeof(values)
对象内存
指的是所有接入到Redis服务器TCP连接的输入输出缓冲
客户端缓冲区
edis在2.8版本之后提供了一个可重用的固定大小缓冲区,用于实现部分复制功能,根据repl-backlog-size参数控制,默认1MB。对于复制积压缓冲区,只有Master节点存在,所有Slave节点共享此缓冲区
复制积压缓冲区
用于在Redis重写期间保存最近的写入命令,其消耗的内存取决于AOF重写时间和写入量,这部分空间占用通常很小
AOF缓冲区
缓存内存
主要是在执行AOF/RDB重写时,Redis创建的子进程内存消耗。Redis执行fork操作产生的子进程,内存占用量与父进程相同,理论上需要一倍的物理内存来完成重写操作
Redis分配器分配的内存总量,也就是内部存储的所有数据内存占用量
used_memory
从操作系统的角度显示Redis进程占用的物理内存总量
user_momery_rss
内存碎片率,used_memory_rss/used_memory的比值
mem_fragmentation_ratio>1时,说明多出的部分内存并没有用于数据存储,而是被内存碎片所消耗;mem_fragmentation_ratio<1时 ,说明可能是操作系统把Redis内存swap到磁盘导致。
mem_fragmentation_ratio
info memory(内存数据统计)
子进程内存消耗
内存模型
指的是Redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除
定期删除
就是指当客户端获取某个key的时候,Redis会检查这个key是否设置了过期时间,如果设置了是否已过期?如果过期了就会删除,不会给客户端返回任何东西。
惰性删除
回收策略
定期删除和惰性删除只能解决内存空间足够情况下的内存回收,如果大量过期key堆积在内存里,导致Redis内存耗尽,或者说内存使用达到了maxmemory上限,此时则会对内存进行淘汰
默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息;(一般没人用)
noeviction
根据LRU算法,删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略;(一般很少使用)
volatile-lru
根据LRU算法删除key,不管数据有没有设置超时属性,直到腾出足够空间为止;(最常用)
allkeys-lru
随机删除所有键,直到腾出足够空间为止;(一般没人用)
allkeys-random
随机删除过期键,直到腾出足够空间为止
volatile-random
在设置了过期时间的键空间中,有更早过期时间的key优先移除。如果没有,回退到noeviction策略
volatile-ttl
淘汰策略
内存关联
内存管理策略
是一次性生成内存快照的方式,也就是把当前Redis进程的数据生成快照,保存到磁盘上。触发RDB持久化的方式有手动触发和自动触发,生产环境一般都是自动触发,都是通过bgsave命令
描述
执行bgsave命令后,Redis主进程会执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短
原理
1,执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在则直接返回;2,父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞;3,父进程fork完成后,bgsave命令返回“Background saving started”信息,并不再阻塞父进程,父进程可以继续响应其他命令;4,子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换;5,子进程发送信号通知父进程RDB持久化完成,父进程更新统计信息
流程
1,RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中Redis的数据,这种多个数据文件的方式,非常适合做定期的冷备;2,RDB对Redis正常的读写服务影响非常小,可以让Redis保持高性能,因为Redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可;3,相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复数据更加快速
优点
1,RDB持久化不能做到实时,因为频繁fork子进程的开销是很大的。所以如果想要在Redis故障时,尽可能减少数据丢失,那应该开启AOF。一般来说,RDB数据快照文件,都是每隔5分钟或者更长时间生成一次;2,RDB每次fork子进程生成数据快照文件时,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,甚至数秒
缺点
优缺点
RDB持久化
是对每条写入命令以append-only的模式写入一个AOF日志文件中,在Redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集
通过appendonly 开启AOF持久化
Redis的所有写入命令(以文本协议格式)会追加到aof_buf缓冲区的末尾,这个缓冲区其实就是操系统的filesystem cache,可以大幅提升磁盘IO的性能
1,命令追加
每次写入AOF缓存后,立即调用操作系统的fsync命令,将数据刷到磁盘。一般不建议配置,因为会大幅降低吞吐量,除非对数据可用性有非常高的要求
always
由操作系统自身去控制何时将os cache中的数据刷到磁盘上,同步周期不可控。一般也不建议配置
no
每隔1秒钟(默认),调用操作系统的fsync命令将数据刷到磁盘。推荐配置
everysec
写入策略(参数appendfsync控制)
2,文件写入
随着AOF日志文件越来越大,需要定期对AOF文件进行rewrite,以达到压缩的目的。因为AOF会记录每一条写命令,所以会导致对于同一个Key,存在多个冗余命令。Redis会创建一个新的AOF文件来替换老文件,新旧两个文件所保存的数据状态完全相同,但是新文件不会包含任何浪费空间的冗余命令
重写流程(主进程通过bgrewriteaof命令进行重写)
3,文件重写
1,AOF可以更好的保护数据不丢失,AOF默认每隔1秒,通过一个后台线程执行一次fsync操作,所以最多丢失1秒钟的数据;2,AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易损坏,即使文件尾部破损,也很容易修复;3,AOF日志文件过大的时候,即使出现重写,由于是后台操作,所以也不会影响客户端的读写。4,AOF日志文件的命令以可读的方式进行记录,非常适合做灾难性的误删除操作的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令删除,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据。
1,对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大;2,AOF开启后,支持的写QPS会比RDB低,因为AOF一般会配置成每秒fsync一次日志文件;3,AOF这种基于命令日志回放的方式,比RDB每次持久化一份完整数据快照的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据,进行指令的重新构建,这样健壮性会好很多
AOF持久化
数据持久化
全量复制
部分复制
redis复制
redis哨兵模式
redis集群模式
redis高可用
redis
0 条评论
回复 删除
下一页