美文网首页
2018-08-08 redis 实现以及原理小记

2018-08-08 redis 实现以及原理小记

作者: _你好_ | 来源:发表于2018-08-08 20:42 被阅读0次

    最近把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
    

    相关文章

      网友评论

          本文标题:2018-08-08 redis 实现以及原理小记

          本文链接:https://www.haomeiwen.com/subject/cgxfbftx.html