redis学习

Redis每个键值对都是由对象组成,其中
    1.数据库键总是一个字符串对象                           sorted set obj
    2.数据库键的值可以是 字符串对象、列表对象、哈希对象、集合对象、有序对象

包含字符串的键值对底层实现为SDS(Simple Dynamic String)
struct sds{
    int len;  //记录buf数组已使用的字节数量
    int free;  //记录buf数组未使用的字节数量
    char buf[];  //字节数组,用于保存字符串
}
获取 长度为O(1) ,防止 扩容空间不足 ,会进行自动扩容

空间预分配(减少 字符串增长 内存重分配次数,避免频繁重新分配空间导致时间浪费)
    1.若len<1MB,则free=len   即大小为 2×len+1字节
    2.若len>1MB,则free=1MB  即大小为  len+1MB+1字节
惰性空间释放(字符串缩短 空间不释放,而是把多出来的字节放到free里,理由同上)

二进制安全
    可以保存任意格式二进制数据(文本、视频、图片等),而不用担心数据丢失
    如:c字符串(只能保存文本) redis\0cluster\0  只显示redis
     兼容部分C字符串函数  ,遵循C字符串以空字符(\0)结尾的惯例


链表 高效的节点重排 顺序性的访问方式 灵活调整长度
    使用地方:链表键、发布与订阅、慢查询、监视器、客户端状态信息、客户端输出缓存区
    特性: 双端、无环(null为终点)、带头尾指针、计数器、多态(数据用无类型指针void)
    dup复制节点保存的值 free释放节点值 match比较是否相等

(哈希键、数据库的底层实现)
字典(使用hash表实现,用链地址法解决冲突) 又称 符号表、关联数组、映射 用于保存键值
对的抽象数据结构
struct dictht{
    dictEntry ** table;  //哈希表数组
    unsigned long size;  //大小
    unsigned long sizemask; //大小掩码,用于计算索引值总是等于size-1
    unsigned long used   //已有节点数量
}dictht;
struct dictEntry{
    void * key;  //键
    union{            //值
        void * val;
        uint64_tu64;    //整数
        int64_ts64;  //整数
    }v;
    struct dictEntry * next;
}dictEntry;

字典
struct dict{
    dictType * type; //类型特定函数 为创建多态字典而设置
    void privdata;  //私有数据 保存需要传给特定函数的可选参数
    dictht ht[2];  //哈希表  一般使用ht【0】  另外一个rehash才使用
    int rehashidx;  //rehash不在进行时值为-1 ,按这个作为数组下标
}
hash=dict->type->hashFunction(key);
index = hash & dict->ht[0].sizemask;

rehash时 扩展操作h[1]的大小为第一个大于等于h[0].used×2 的2^n
         收缩操作h[1]的大小为第一个大于等于h[0].used   的2^n
         rehash后 释放h[0],然后将h[1]设为h[0],并且在h[1]新建一个空白表

rehash条件 扩展 服务器未执行执行bgsave或bgrewriteasf命令 负载因子大于等于1
                服务器执行执行bgsave或bgrewriteasf命令 负载因子大于等于5
           收缩,负载因子小于0.1

渐进性rehash ,hash操作并非一次完成,分多次(防止服务器负载过大)


跳跃表(效率近似平衡树,且实现简单  实现 有序集合键 、集群节点作为内部数据结构)


整数集合 用于保存整数值的集合抽象数据结构 可保存int16_t int32_t int64_t整数值
typedef struct intset{
    uint32_t encoding; //编码方式 值为insert_ENC_int16 、32、64
    uint32_t length;   //包含元素数量
    int8_t contents[]; //保存元素的数组、各项在数组中按值的大小排序,无重复项
}intset;

当插入元素大于当前编码方式的时候会进行升级扩容 提升灵活性、尽可能节约内存
不支持降级


压缩列表(列表键、哈希键的底层实现之一)
    一个列表建只包含少量列表项,则会用压缩列表实现
4(记录占用内存字节数)+4(记录连尾节点到起始节点有多少字节)+2(节点数量)+
节点。。。+特殊值(标记压缩列表末端)

节点   上一个节点长度prelength+编码+content数组
连锁扩展  当节点长度超过 prelength 所有节点的 prelength 会连锁扩容


对象类型与编码
    String 、list、hash、set、有序集合对象

String 编码可以是int 、raw、embstr


类型检查与命令多态
    1.可以对所有类型使用
    del、expire、rename、type、object、dbsize等
    2.只能对特定对象使用
    String  set、mset、get、append、strlen等
    hash   hdel、hset、hget、hlen等
    list   rpush、lpop、linsert、llen等
    set    sadd、spop、sinsert、scard等
    zset   zadd 、zcard、zrank、zscore等

内存回收:引用计数 int refcount; 创建新对象时初始化为1,为0时会被回收

对象共享 包含值int的字符串对象、嵌套字符串对象(linkedlist、hashtable、zset、set)
为字符串的不共享、验证操作浪费CPU

            LRU
对象空转时长 lru属性 记录最后一次被访问时间,超过maxmemory旧的被优先释放

#redisServer.db存放数据库  redisServer。dnum存放数量
切换数据库 select 数据库号码   默认为0号数据库
新增、更新set   key    value
    String    string、list、hashtable、set、在set、
字典保存了数据库中所有键值对(称为键空间)

删除 del key

取值 get key

清空数据库 flushdb  返回数据库键数量 dbsize 、exists、rename、keys

expire key 5     second 设置键的生存时间或过期时间 或pexporeat
TTL key   显示剩余生存时间second   PTTL   毫秒显示

expores字典(过期字典)存放了所有键过期时间

persist移除过期时间


过期键删除策略
    1.定时删除 设置过期时间同时创建定时器,定时器过期时立马删除(内存友好,cpu紧张不建议使用)
    2.惰性删除 不管过期,每次取数据都检测键是否过期(内存不友好,可能内存泄漏)
    3.定期删除  每隔一段时间删除(合理设置)

AOF持久化、RDB持久化和复制功能对过期键的处理
生成RDB文件
    执行save、bgsave会创建一个新的RDB文件,过期键不会保存到RDB中
RDB文件载入:
    主服务器模式运行:RDB文件中未过期的键会载入,过期忽略
    从服务器:所有键值对都会载入。主服务器进行数据同步时,从服务器数据库会被清空

AOF文件写入
    以AOF持久化模式运行,数据库某个键过期,但是没被删除,那么AOF文件不会因为这个过期
    键有任何影响,当被删除以后程序会向AOF文件追加一个DEL命令,来显式记录该键已删除

AOF重写
    过期键不会保存

复制
    服务器运行在复制模式下,从服务器的过期删除动作由主服务器控制,从服务器不会处理过期
    键,会像正常键一样对待,接受到主服务器DEL命令才会删除


数据库通知
    让客户端通过订阅给定的频道或模式来获知数据库中键的变化,已经命令执行情况


RDB持久化
    非空数据库以及他们的键值统称为数据库状态
save会阻塞Redis服务器进程 
bgsave会派生子进程不阻塞服务器进程(执行期间save bgsave bgrewriteaof会被拒绝)
RDB载入,在服务器启动时自动扫描执行(若开启了AOF,优先载入AOF)

save 100 10 //距离上次成功备份已经100秒内执行至少10次修改,则自动间隔性备份(即执行bgsave)


dirty计数器:记录上一次成功执行save命令后,对数据库状态进行了多少次修改
lastsave属性:记录上一次修改时间

周期性操作函数serverCron默认每隔100毫秒检测一次save选项所设置保存条件是否满足


RDB文件结构  
      5字符        4字节                1字节   8字节无符号整数
    REDIS   +   db_version+ database + EOF + checknum
   判定是否RBD文件          selectdb+dbnumber+key_value_pairs(1+1、2、5+...)
key_value_pairs = (expiretime_ms 1+ms 8)type +key+value
value = encoding+integer  //其中字符串小于等于20字节,原样保存,大于20压缩后保存

AOF通过保存服务器所执行的写命令来记录数据库状态
命令追加(放入aifbuf)+Aof文件写入与同步

aof重写 当命令过多时,需要重写,如一个对象的操作会合并成一条语句

事件类型
    1.当套接字变得可读时(客户端执行write、或close)或则有新的应答acceptable
       套接字产生read事件
    2,套接字变得可写时(客户端执行read),产生write事件

redis 数据结构
    String  set get del 可对数值自增自减

   mset  key value [k v .......]
        decr keyname     incr keyname       key对应的value自增1  
        incrby keyname count   value+=count      decrby
        incrbyfloat

    append key-name value   追加value到 key的value的末尾
    getrange   key-name  x y   取x到y范围内的所有值,包括xy
    setrange  key-name  offset  value  从start开始偏移量设置子串为指定值 
    getbit key-name offset 字节串看做二进制串,获取串中偏移为offset的二进制位的值
    setbit key-name  offset  value  
    bitcount key-name [start end]  统计二进制串的1的个数
    bittop  operation dest-key key-name [key-name ...] 对一个或多个二进制串执行
        and  or  xor  not 操作

    List    
        lpush入左  rpush   lpop rpop     eg: rpush  key-name item [,item...]
        lindex  key-name offset  获取指定位置元素 
        lrange获取给定范围所有元素  lrange list-key start end  
        ltrim  key-name start end 对列表进行修剪,只保留start到end的元素(包含s、e)
        blpop  key-name、... timeout   阻塞获取时延为timeout
        brpop
        rpoplpush list1 list2   从list1右边出栈一个元素,入栈到list2最左端
        brpoplpush list1 list2 timeout   带时延的


    HASH 可对value数值自增自减  

         hset  
         hmset hash-key sub-key1 value1 [sub-key2 value2 ... ]
         hmget hash-key key [key1 ,...]
         hlen hash-key 
         hdel hash-key  key [key1 ,...]

         hexists hash-key key  
         hkeys hash-key 获取所有键
         hvals hash-key 获取所有值
         hgetall hash-key    获取所有键值
         hincrby hash-key key count
         hincrbyfloat

    SET   
        sadd key-name item、...   添加 
        srem key-name item、...   移除  
        sismember  key-name item 是否包含该元素
        scard    key-name   返回集合包含元素数量
        smembers key-name  获取所有元素  
        srandmember key-name [count]   从集合中随机返回一个元素,count为正数,返回随机元素
                              不会重复,为负数时会出现重复
        spop key-name 随机移除一个元素
        smove set1 set2 item  若set1中包含item,移除item并添加到set2中

        sdiff key-name [key-name...]返回存在于第一个集合、但是不存在于其他集合的元素
        sdiffstore dest-key  key-name [key-name...]  将上一个操作的结果存到dest-key中
        sinter  key-name [key-name...] 返回同时存在于所有set的元素
        sunion key-name [key-name...]  并集运算
        sunionstore dest-key  key-name [key-name...]  并存储
  


    ZSET 
        zadd zset-key 728 member1 [score member ...]
        zrem zset-key member                      删除
        zcard zset-key                          返回有序集合包含的成员数量
        zincrby zset-key member count            member的分数加count
        zcount zset-key min max                返回介于 min max间的成员
        zrank zset-key member                   获取member在集合中排名
        zscore zset-key member                   获取member分数
        zrange zset-key 0 -l withscores
        

        zrevrank zset-key member      返回有序集合member排名,分值由小到大
        zrevrange zset-key start end [withscores]      由大到小
        zrangebyscore zset-key  min max [withscores] [limit offset count] 
                              (获取指定分数范围的元素)  
        zrevrangebyscore zset-key  min max [withscores] [limit offset count]  
                                由大到小
        zremrangebyrank  zset-key start end   删除按排名
        zremvrangebyscore zset-key  min max      删除按分数
        zinterstore   交   分值累和
        zunionstore  并    分值取少的


subscribe channel [channel...]
unsubscribe [channel [channel...]] 退订频道,若未指定,则全部退订
publish channel message 向指定频道发送消息
psubscribe pattern [pattern...]   订阅与给定模式匹配的所有频道
punsubscribe [pattern [pattern...]]    退订与给定模式匹配的所有频道


事务   pipeline()获取事务流水线 ,然后对流水线进行以下操作

   watch 监控事务要修改的键,直到exec命令期间,若被其它客户端修改,则事务失败,可选重试或放弃 

   unwatch

    watch执行后 discard 可以清空命令队列
    multi  标记事务开始
    中间接收到的所有命令都会放入队列,直到执行完
    exec   标记结束  在这个命令前输入的所有命令不会执行

非事务也可以通过pipeline提高执行效率,减少了通信往返次数

 


数据安全与性能保证
    RDB(快照)   bgsave  save  
        若备份途中系统崩溃,则丢失所有数据
        
        redis接收到shutdown命令时,会自动执行save,完毕后关闭
        
        当服务器连接到另外一台redis服务器时,并向对方发送sync命令来开始一次复制操作
        的时候,如果主服务器目前没有在执行bgsave操作,或并非刚刚执行完bgsave,那么
        主服务器会执行bgsave。

                                              由OS决定写入,但是会导致阻塞性能降低
    AOF(append only file)  频率 always everysec   no  (写入缓冲区满了)

    AOF 重写、压缩    bgrewriteaof

    复制  主从服务器之间数据同步

    slaveeof  [host port]         设置从服务器
    1.使用的配置设置,从服务器启动会先载入自己的 备份文件,然后进行同步,操作如下
        

    2.使用命令的话,从服务器会直接尝试连接主服务器,成功后过程相同

    PS:主从服务器进行初始连接时,数据库中所有数据会丢失并替换为主服务器的数据
        不支持 主 主 复制

主从链::

从服务器可以拥有从服务器,唯一的区别在于,从服务器进行步骤4时,从服务器的从服务器连接会断开。

 

验证主服务器的aof写命令是否发送到从服务器,用户需要在向主服务器写入真正数据后,再向主服务器写入一个唯一虚构值,

通过从服务器是否存在虚构值来判定数据是否已经到达从服务器。

检测info命令输出结果的aof_pending_bio_fsync属性是否为0,为0表示服务器已经把所有数据保存到硬盘了

 

redis-benchmark   获取redis服务器性能特征

 

分布式锁的构建(watch【乐观锁】有时候不能满足需求,并且会导致性能问题)

处理线程生成唯一的uuid的identifier,传入 setnx    setex 中  设置独占锁  限时锁可以通过设置uuid的有效期expire来实现

 

信号量

    生成标识符identifier,清理过期标识符,新的标识符加入有序集合,检测新的标识符在集合中的排名,检测是否成功获取,失败则删除identifier

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值