Redis分享一

作者: 何甜甜在吗 | 来源:发表于2018-05-28 13:41 被阅读0次

Redis介绍

开源免费的高性能key-value数据库

Redis的应用场景

Redis作者提出的九个应用场景

  • 取最新N个数据的操作
    比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的5000条评论的ID放在Redis的List集合中,并将超出集合部分从数据库获取

    1. 使用LPUSH latest.comments<ID>命令,向list集合中插入数据
    2. 插入完成后再用LTRIM latest.comments 0 5000命令使其永远只保存最近5000个ID
      Ltrim 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
  • 排行榜应用,取TOP N操作
    这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可
    利用有序集合的性质

  • 需要精准设定过期时间的应用

  • Uniq操作,获取某段时间所有数据排重值
    使用Redis的set数据结构,只需要不断地将数据往set中扔就行了,set都保证集合中的元素都是唯一的

  • 实时系统,反垃圾系统

  • Pub/Sub构建实时消息系统

  • 计数器应用

  • 构建队列系统
    使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统

  • 缓存
    附:原文地址:Redis作者谈Redis应用场景

Mysql 有自己的缓存机制 ,为什么还要用Redis缓存Mysql数据

mysql查询过程.jpg
  • 这个缓存是本地缓存,如果有多台服务器,sql语句会随机发送给其中一台,无法保证相同的请求会发送给同一台,这样本地缓存命中率就比较低,本地缓存(即查询缓存)就没有什么用了
  • 从查询缓存中取出结果或者将查询结果添加进查询缓存中,会带来额外性能消耗
  • 当表的结构或内容发生变化时,使用这个表的缓存查询将不再有效,查询缓存值的相关条目将被清空。常见修改表结构和表内容的语句,如delete、insert、altert able很多。使用redis作为缓存将受这个影响很小,因为它是基于键值对保存缓存的,只有key对应的缓存内容发生变化,才会受到影响,其他key对应缓存内容发生变化对其几乎是没有影响的

数据类型

支持五种数据类型

  • 字符串 (String)
  • 哈希 (Hash)
  • 列表 (List)
  • 集合 (Set)
    无序不重复
  • 有序集合(sorted set)
    在Set的基础上每个元素都会关联一个double类型的分数。redis通过分数来为集合中的成员进行从小到大的排序。
    有序集合的成员是唯一的,但分数(score)却可以重复

Redis和Memcached的区别

  • Redis支持的数据类型更丰富

  • Redis支持持久化,满足条件时会进行持久化
    比如900秒内进行1次修改 300秒内进行10次修改 60秒内进行10000次修改就会进行一个持久化将数据保存在磁盘中
    Redis提供两种持久化的方式 AOF RDB 默认是RDB
    Memcached把数据全部存储在内存中,断电后会挂掉

  • IO模型不同 (待补充,下次分享讲)
    Redis:单线程非阻塞IO复用 模型
    Memcached:多线程非阻塞IO复用

  • 集群管理的不同 (待补充,下次分享讲)

String数据类型的底层实现

String的底层实现为SDS(简单动态字符串)
数据结构:

struct sdshdr {
    int len;
    int free;
    char buf[];
};
SDS示例.png
free:未使用的空间
len:保存字符串的长度,'\0'不做统计
buf:char类型数组

SDS与C字符串的区别

  • SDS常数复杂度获取字符串长度,直接从len属性中读取,时间复杂度为O(1)
    C字符串不记录自身长度的长度信息,获取字符串的长度必须遍历整个字符串,时间复杂度为O(n)

  • Redis通过空间分配策略完全杜绝了发生缓冲区溢出的可能性。当SDS API需要对SDS进行修改时,API首先会检查SDS的空间是否满足修改所需的要求,如果不满足,API会自动将SDS的空间扩展至执行所需的大小,然后在执行实际的修改操作
    C字符串执行某些操作时若没有人工分配足够的内存,将会造成缓冲区溢出

  • 减少修改字符串时带来的内存重分配次数

    1. 空间预分配
      当需要对SDS进行空间扩展时,程序不仅会为SDS分配修改所需要的空间,还会为SDS分配额外的未使用空间
      分配策略

      • SDS的长度小于1MB,程序分配和len属性同样大小的未使用的空间
        即如果进行修改以后,SDS的len变成13字节,那么程序也会也会分配13字节未使用空间,实际长度13byte+13byte+1byte
      • SDS的长度大于1MB,程序将会分配1MB的未使用空间
        即如果进行修改以后,SDS的len变成2MB,那么程序也会会分配1MB未使用空间,实际长度30MB +1MB+1byte
    2. 惰性空间释放
      当SDS的API需要缩短SDS保存的字符串时,程序不会立即使用内存重分配立即回收缩短后多出来的字节,而是使用free属性将这些字节的数量记录起来,等待将来使用。如果需要真正释放SDS的未使用空间。可以通过调用sdsfree API

好处:减少内存分配次数

  • 二进制安全
    SDS的API都是二进制安全的,所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据,数据在写入时是什么样,它被读取时就是什么样的

  • 兼容部分C字符串函数
    通过遵循C字符串以空字符串结尾的惯例,SDS在有需要的时候可以重用<string.h>函数库,避免了不必要的代码重复

参考:
《Redis设计与实现》
《高性能MySQL》

相关文章

网友评论

    本文标题:Redis分享一

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