Redis之路系列(1)千里之行始于足下

01 千里之行始于足下

文章内容基于redis6

安装与运行

无论你一名极客还是一名工程师,Redis安装我都推荐源码安装,请前往官方下载地址:http://redis.io/download 进行源码下载,偶数为稳定版 奇数为不稳定版。

如果你是类linux系统,使用wget命令直接远程下载源码 wget https://download.redis.io/releases/redis-{具体版本号}.tar.gz

编译与安装命令:make && make install
默认安装地址:/usr/local/bin ,准备好redis.conf配置文件,以下几个配置建议修改:

daemonize yes  后台启动
port xxxx  修改默认端口
requireoass xxxx   添加访问密码
bind 127.0.0.1 如果想其它服务器可以访问,注释掉

服务端启动运行命令: ./redis-server ../conf/redis.conf

服务端停止运行命令:pkill redis-server 或者使用客户端发出关闭命令: ./redis-cli shutdown

客户端链接命令:./redis-cli -h 服务器IP -p 端口 -u 用户 -a 密码 ,建议更换默认端口,添加访问认证密码

redis版本号查看命令:redis-server -v

redis自带工具集

  • redis-benchmark:性能测试工具,测试redis在你的系统及配置下的读写性能
  • redis-check-aof:用于修复出问题的AOF
  • redis-check-rdb:用于修复出问题的rdb
  • redis-sentinel:redis的集群管理工具

两种线程模型

  • 单线程模型:socket读写、解析数据、执行处理、返回数据等操作都是由一个主线程来完成的。通过对epoll函数的包装来做到。

    单线程原因:瓶颈在内存和网络不在cpu、多线程可能不安全、复杂度增加、线程上下文切换性能损耗等

  • 多线程模型:redis6开始支持I/O多线程,因为之前的瓶颈主要在I/O数据读写性能

高性能根本原因:抽象了一套事件模型,使用多路复用机制(epoll),使得I/O读写都是非阻塞的,从而具备高性能的网络处理能力;同时基于内存进行数据处理。

value存储形式

我们日常中所提到的String(字符串)、List(列表)、Hash(哈希)、Set(集合)和 Sorted Set(有序集合)都只是Redis 键值对中值的数据类型,也就是数据的保存形式。

严格来说并不是Redis数据结构,Redis底层数据结构实现其实一共有6种:分别是简单动态字符串(SDS)、双向链表、压缩列表、哈希表、跳表和整数数组。具体对应关系,后面介绍底层存储结构时会进一步介绍。

先理解和掌握value的5种基本存储形式

String

key是字符串,如果存在空格必须加上双引号,最大的容量是512M
在这里插入图片描述

类似Memcache的键值存储,

  • 使用场景:缓存、计数、共享会话、限速
List

底层实现是链表

在这里插入图片描述
类似数据结构中的队列,不过支持双向操作。

  • 使用场景:消息队列、文章列表
Hash

按hash的方式存放字符串

在这里插入图片描述

相当于关系数据的行数据

  • 使用场景:存储类似于关系数据库的行
Set

是通过hashTable实现的

在这里插入图片描述

存储很多数据名单又不重复,判断某个元素是否存在相当方便,聚合运算效率也很高(存放好友,联系人,共同好友)

  • 使用场景:标签,分类,社交
Zet

是通过散列表和跳跃表来实现的

在这里插入图片描述

在Set基础上增加了有序的特点,增加了一个double类型的分数作为权重,用于排序

  • 使用场景:排行榜、社交点赞

存储基本结构

整体上看,无论是哪种存储形式,Redis都是键-值的形式,为了实现这种从键到值的快速访问,Redis使用了一个哈希表来保存所有的键值对。

一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。所以,我们常说,一个哈希表是由多个哈希桶组成的,每个哈希桶中保存了键值对数据。

在这里插入图片描述
每个键值对包含了键部分和值部分,键部分都是String类型,值部分由大家所熟知的(上面介绍的)5种存储结构组成,而底层用来实现的数据结构有6种,它们之间的对应关系如下:

在这里插入图片描述

上面这个哈希表保存了所有的键值对,也称作全局哈希表。当Hash表查询数据的时间复杂度是O(1),操作又是内存级别的,所以数据会非常快。

不过当redis存储的数据越来越大的时候,难免就会产生hash冲突,形成链式hash,hash链上的元素只能逐个查找,时间复杂度是O(n),所以效率就会下降。

在这里插入图片描述

当链式hash过程的时候,redis会进行rehash操作,保证元素分布均匀。rehahs的过程是一个渐进式的过程。可以分为3个步骤:
1 先构造一个更大的全局哈希表;
2 映射元素到新的全局哈希表;
3 释放掉旧的hash表。

这里的关键是第2步,redis不是一次性完成所有元素拷贝的,而是在某索引位置发生请求或空闲时,才进行拷贝。

巧妙的把一次性大量拷贝分摊到了多次请求的过程中,既不影响正常请求也能保证数据快速拷贝(后续AOF重写技术也利用了这个设计)。

熟悉了底层数据结构的实现,对我们如何使用redis提供了技术指导,操作的复杂度取决于数据结构的复杂度:

  • 对Hash和Set的单元素操作,其实现是哈希表,复杂度都是O(1),它们现在也支持了多元素操作,M个元素复杂度就是O(M)
  • 对List、Hash、Set遍历操作时其实现是通过链表或数组实现,复杂度一般为O(N),我们尽量避免这种操作
  • 对集合类型元素统计操作(LLEN,SCARD),一般会有单独的字段来存储这个值,所以复杂度为O(1)
  • 特别注意对与压缩列表和双向列表都会记录头尾指针偏移量,对与头尾类操作(LPOP,RPUSH),复杂度为O(1)

通用规则

  • List、Hash、Set、Zset被称作容器型数据
  • 不存在就创建原则:容器型数据不存在,就会自动创建一个,再进行操作
  • 没有就释放原则:容器型数据中如果没有元素了,就删除掉并释放内存
  • 能有过期时间:所有数据结构都可以设置过期时间
  • 过期时间擦除:对有过期时间的字符串进行修改操作会抹除掉过期时间

过期机制

设计理念基于性能与效率的折中,采用定期删除与惰性删除机制

定期删除:Redis会在后台,默认每秒10次的执行如下操作: 随机 选取100个key校验是否过期,如果有25个以上的key过期了,立刻 额外随机选取下100个key(不计算在10次之内)。也就是说,如果过 期的key不多,Redis最多每秒回收200条左右,如果有超过25%的 key过期了,它就会做得更多,这样即使从不被访问的数据,过期 了也会被删除掉。

惰性删除:当client主动访问key时,会先对key进行超时判断,过 时的key会立刻删除
处理过期keys的相关命令:

  • expire:设置过期时间,格式是expire key值 秒数
  • expireat:设置过期时间,格式是expireat key值 到秒的时间戳
  • ttl:查看还有多少秒过期,格式是ttl key值,-1表示永不过期,-2表示已 过期
  • persist:设置成永不过期,格式是persist key值,删除key的过期设置;另 外使用set或者getset命令为键赋值的时候,也会清除键的过期时间
  • pttl:查看还有多少毫秒过期,格式是pttl key值
  • pexpire:设置过期时间,格式是pexpire key值 毫秒数
  • pexpireat:设置过期时间,格式是pexpireat key值 到毫秒的时间戳
  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值