最近把redis实现以及原理这边书过了一遍,本文为该书阅读过程中的一些纲要以及重要知识点的小记,方便日后查阅。
推荐书籍:redis设计与实现
本文中所摘录的内容大部分来自该书
redis 类型
redis 类型 | 地层数据结构 | 特点 |
---|---|---|
REDIS_STRING | REDIS_CODING_INT | int 类型的字符串 |
REDIS_STRING | REDIS_CODING_EMBSTR | 长度小于32字节的字符串 |
REDIS_STRING | REDIS_CODING_RAW | 长度大于等于32字节的字符串使用sds |
REDIS_LIST | REDIS_CODING_ZIPLIST | 压缩表,值小于64字节,表长不大于512 |
REDIS_LIST | REDIS_CODING_LIKNEDLIST | 双向链表 |
REDIS_HASH | REDIS_CODING_ZIPLIST | 压缩表,keyvalue 为一个节点 |
REDIS_HASH | REDIS_CODING_HT | 哈希表,键或值不小于64或表长大于512 |
REDIS_SET | REDIS_CODING_INTSET | 整数集合,全部为整数,表长不大于512 |
REDIS_SET | REDIS_CODING_HT | 哈希表 |
REDIS_ZSET | REDIS_CODING_ZIPLIST | 压缩表 value score, value小于64字节,长度不大于128 |
REDIS_ZSET | REDIS_CODING_SKIPLIST | 跳跃表 |
tips
redis 的 zset 如果使用 skiplist 则会同时创建 skiplist跟dict,以便结合使用获取到更高的性能,如查找单个元素可以使用字典加速,如使用 zrank zrance 等命令,则使用跳跃表以便有序的访问相关节点。
命令
# 查询对象的编码信息
object encoding key <subkey>
# 查询对象的lru时间
object idletime key
redis key 过期操作
redis 惰性删除以及定期删除结合淘汰过期键
惰性删除:在操作数据是如getset等操作时检测是否过期,如果过期则将该条数据删除
定期删除:每隔一段时间循环遍历所有的db,从db中随机选取一部分key,检测是否过期。该循环遍历过程可能发生在多个时间周期内(比如这次遍历了2个db,下次继续之前的index继续遍历),每个时间周期的最长执行时间以及最大检测key个数均有设置,超过了则停止,下次继续上次的db遍历。
RDB 保存快照的备份方式 (Relational Database)
save 阻塞所有客户端请求
bgsave 后台处理保存快照的命令
在使用保存功能时,不保存以及过期的键
如果服务器开启了RDB功能,那么在服务器启动时,将对RDB文件中的保存的键进行检查,如果未过期则载入到内存中。载入RDF文件时,服务器会阻塞所有客户端请求
# 60秒之内对数据库至少进行了10000次修改则执行 besave命令
save 60 10000
# 多个条件可以分别触发,比如达到了5秒内200次也会执行 basave命令
save 5 200
AOF binlog 的模式 (Append Only File)
当键过期时并不会立即存储到log文件中,而是等到真正的清除的时候,即执行惰性删除或者定期删除的时候追加 del 命令到log文件中。
AOF文件重写,fork新进程写新文件,fork之后的命令缓存,待新文件写完毕以后将缓存的命令追加的新的文件中,然后用新的文件替换旧的文件
追加文件的模式有三种,
模式 | 描述 |
---|---|
always | 一条命令刷新一次 |
everysec | 超过一秒未刷新则此次写入刷新 |
no | 不刷新,只write不flush,让操作系统自己管理 |
主从模式下的 过期策略
主服务器会启用惰性删除以及定期删除,当删除过期键时,发送del命令到从服务器,从服务器执行删除逻辑。
而从服务器是不会主动处理过期键的,除非从主服务器接收到了del命令,比如执行get命令时,从服务器发现键以及过期,但是不会执行删除命令,而是将键返回给客户端。
而当主服务执行get命令是,发现过期键,则会执行del,并且将del命令发送给从服务器,并且返回客户端null
redis 发布订阅
# 订阅 test_channel
subscribe test_channel
# 订阅 pattern
psubscribe test_channel[12]
# 在 test_channel 上面发布 hi消息
publish test_channel hi
# 其他查询命令
pubsub channels
pubsub numsub
pubsub numpat
事务
watch name
multi
set name "test"
get name
exec
如果exec执行钱,name的值被其他客户端修改了,则服务器拒绝执行该事务
/**
* 以下代码使用spring redis获取
* redis 事务
* 如果 watch 的 test_msg 在观察之后发生了写入事件变化
* 则该事务不会执行成功
* 事务的执行在exec时才会发生
* 如果执行成功则返回test_msg的值否则返回空列表
*/
@Test
public void test() {
stringRedisTemplate.setEnableTransactionSupport(true);
stringRedisTemplate.watch("test_msg");
stringRedisTemplate.multi();
stringRedisTemplate.opsForValue().set("test_msg", "value");
stringRedisTemplate.opsForValue().get("test_msg");
List<Object> exec = stringRedisTemplate.exec();
System.out.println(exec);
}
集群模式
redis集群不同节点通过分配不同的slot组成一个集群
该集群中,如果访问任一个节点后执行key相关命令
则集群节点会将该key hash到 0-16383 中的一个slot中,并且
集群中slot会被设置到集群节点上,如果该key在所访问的节点上则执行,
否则返回 moved 命令,客户端接到moved命令后,根据moved命令的ip端口
访问slot所在的集群节点。
# 集群配置 将 ip port 加入到本机所在的集群网络
cluster meet ip port
# 查看集群内节点信息
cluster nodes
# 给当前节点添加slot (0-16383)
cluster addslots slot1 <slot2...>
cluster addslots {0..5000}
# moved 命令返回给客户端,客户端会自动访问新的ip端口,即slot所在的节点
moved slot ip:port
小计
slot分布
moved ack 命令区别
集群同步相关
# 集群模式连接服务器
redis-cli -c -p 7000
# 单机模式连接服务器
redis-cli -p 7000
tips: 单机模式下连接,服务器返回moved命令客户端不会自动重定向
集群
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
节点
CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
槽(slot)
CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
键
CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。
原子操作
# 如果key不存在则添加,否则返回null且不更新
set key value nx
# incr 自增后为21 该操作为原子性的
# decr 自减后为20 该操作为原子性的
# incrby 增加后为30 该操作为原子性的
set page_value 20
incr page_value
decr page_value
incrby page_value 10
一些其他命令小计
select db_name
setex str_key str_value key_at_time
expireat key at_time
pexpireat key at_time_ms
expire key ttl
expre key ttl_ms
ttl key
pttl key
persist key
set key value
sadd key value1 <value2 ...>
rpush key value1 <value2 ...>
client list
client setname clientname
# 主从配置
slaveof 127.0.0.1 6379
sort
rpush test_list 5 3 2 1 4
sort test_list
sort test_list asc
sort test_list desc
sadd fruit "banana" "apple" "cherry"
sort fruit alpha
1) "apple"
2) "banana"
3) "cherry"
mset apple-price 8 banana-price 5.5 cherry-price 7
sort fruit by *-price
1) "banana"
2) "cherry"
3) "apple"
mset apple-id "fruit-08" banana-id "fruit-55" cherry-id "fruit-70"
sort fruit by *-id alpha desc
1) "cherry"
2) "banana"
3) "apple"
sort fruit by *-id alpha asc limit 1 2
1) "banana"
2) "cherry"
sadd students "perter" "jack" "tom"
mset perter-name "Perter White" jack-name "Jack Snow" tom-name "Tom smith"
sort students alpha get *-name
1) "Jack Snow"
2) "Perter White"
3) "Tom smith"
sort students alpha store sorted_students
lrange sorted_students 0 -1
1) "jack"
2) "perter"
3) "tom"
#### 完整版如下 类 sql
sort <key> alpha desc by <by-pattern> limit <offset> <count> get <get-pattern> store <store-key>
bit 操作
setbit
getbit
bitcount
bittop
# 设置0位为1
setbit bit 0 1 # 0000 0001 >0
setbit bit 3 1 # 0000 1001 >0
setbit bit 0 0 # 0000 1000 >1
# 获取0位的值
getbit bit 0 # 0000 1000 >0
getbit bit 3 # 0000 1000 >1
# bit count 1的数量
bitcount bit # 0000 1000 >1
bittop and andresult bit1 bit2 bit3
bittop or orresult bit1 bit2 bit3
bittop xor xorresult bit1 bit2 bit3
bittop not notresult bit1
网友评论