Redis学习[数据结构、过期策略]

Redis的学习【数据结构、过期策略】

  • Redis是什么,能干什么?
  • Redis的安装
  • Redis基础数据结构
    • string
    • list
    • map
    • set
    • zset
  • 过期策略
    • 过期的key集合
    • 定时扫描策略
    • 从节点的过期策略

Redis是什么,能干什么?

  1. Redis(Remote Dictionary Service 远程字典服务)是互联网技术领域使用最为广泛的存储中间件。Redis是一个key-value等多种数据结构的存储系统,高性能的key-value数据库。

  2. Redis应用场景,能做什么

      众多语言都支持Redis,因为Redis交换数据快,在服务器中常用来存储一些需要频繁调取的数据,节省内存开销,也极大的提升了速度。
    
     将一些热点数据存储到Redis中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。
    
     1、会话缓存(最常用) 
    
     2、消息队列(支付)
    
     3、活动排行榜或计数
    
     4、发布,订阅消息(消息通知)
    
     5、商品列表,评论列表
    

Redis的安装

1. Docker方式

# 拉取Redis镜像
> docker pull redis
# 运行Redis客户端
> docker run -- name myredis -d -p6379:6379 redis
# 执行容器中的redis-cli,可以直接使用命令操作Redis
> docker exec -it myredis redis-cli

2. Github源码编译方式

# 下载源码
> git clone --branch 2.8 --depth 1 [email protected]:antirez/redis.git
> cd redis
# 编译
> make
> cd src
# 运行服务器,daemonize表示在后台运行
> ./redis-server -- daemonize yes
# 运行命令行
> ./redis-cli

3. 直接安装方式

# mac
> brew install redis
 # ubuntu
> apt-get install redis
# redhat
> yum install redis
# 运行客户端
> redis-cli

Redis基础数据结构

	Redis共有5种数据结构:string(字符串)、list(列表)、hash(字典)、set(集合)、zset(有序集合)

string

    字符串string是Redis最简单的数据结构,它的内部表示就是一个字符数组。Redis所有数据结构都以唯一的key字符串作为名称,然后通过这个唯一的key值获取相应的value数据。不同数据结构的差异就在于value的结构不一样。
    字符串最常见的用途就是缓存用户信息。我们将用户信息结构体使用JSON序列化成字符串,然后将序列化的字符串塞进Redis缓存,取用户信息会经过一次反序列化的过程。
    Redis的字符串是动态字符串,是可以修改的字符串,内部结构类似Java中的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。内部为当前字符串分配的空间capacity(容量)一般要高于实际字符串长度。当字符串长度小于1MB时,扩容都是加倍现有空间。如果超过1MB,扩容时一次只会多扩1MB的空间,字符串最大长度为512MB。

list

    Redis的列表似于Java中的LinkedList,底层是一个快速链表(quicklist),当列表元素较少时,会分配一块连续的内存用于存储,这个结构是ziplist(压缩列表),它将所有的元素彼此紧挨着一起存储,当元素较多时则改成quicklist。因为普通列表需要的 附加指针(prev,next) 空间太大,会浪费空间,还会加重内存的碎片化。ziplist使用双向指针串起来使用就成了quicklist。满足快速插入的性能,又不会出现太大的空间冗余。

map

    Redis中的字典相当于Java中的HashMap,它是无序字典,内部存储了很多键值对,实现结构与JDK1.7一样,也是"数组+链表"二维结构。不同的是,Redis的字典的值只能是字符 串,另外他们rehash的方式不一样,Java的HashMap在字典很大的时候,rehash是个耗时的操作,需要一次性全部rehash,Redis为了追求高性能,不能阻塞服务,采用渐进式rehash策略
    渐进式rehash会在rehash的同时,保留新旧两个hash结构,查询时会同时查询两个hash结构,然后在后续的定时任务以及hash操作中,循序渐进地将旧hash内容一点点地迁到新的hash结构中。当搬迁完成了,就会使用新的hash结构取而代之。hash还能对用户结构中的每个字段单独存储,获取用户信息时就能单独获取,用字符串的形式则需要一次性全部读取,会浪费网络流量。但hash结构的存储消耗要高于单个字符串。

set

    Redis的集合相当于Java中的HashSet,内部键值对是无序且唯一的。内部实现相当于一个特殊的字典,字典中所有的value都是NULL值。
    set结构可以用来存储在某活动中奖用户的ID。

zset

    类似Java中SortedSet和HashMap的结合体,一方面它是set,保证了内部value的唯一性,另一方面他可以给每一个value附一个score,代表这个value的排序权重。内部实现用的是一种叫作“跳跃列表”的数据结构。

跳跃列表:zset内部的排序功能是通过“跳跃列表”数据结构来实现的,因为zset要支持随机的插入和删除,所以它不宜使用数组来表示。跳跃列表类似金字塔结构

    zset可以用来存储粉丝列表,value值是粉丝ID,score是关注时间,我们可以对粉丝列表按关注时间进行排序。

过期策略

Redis所有的数据结构都可以设置过期时间,时间一到就会被自动删除

过期的key集合

    Redis将每个设置了过期时间的key放入一个独立的字典中,以后会 定时遍历(集中处理) 这个字典来删除到期的key。除了定时遍历外,他还会使用 惰性策略(零散处理) 来删除过期的key。所谓惰性策略就是当客户端访问这个key时,Redis对key的过期时间进行检查,如果过期了就立即删除。

定时扫描策略

    Redis默认每秒进行10次过期扫描,过期扫描不会遍历过期字典中所有的key,而是采用了一种贪心策略
1)从过期字典中随机取20个key
2)删除这20个key中已经过期的key
3)如果删除的key比例超过1/4,重复步骤一
同时为了保证过期扫描不会出现循环过度,导致线程卡死的现象,算法还增加了扫描时间上限,默认不超过25ms
    假设一个大型Redis实例中所有的key在同一时间过期了,Redis会持续扫描过期字典(循环多次),直到过期字典中过期的key变得稀疏,才会停止(循环次数明显下降),这就导致线上读写请求出现明显的卡顿现象。导致卡顿的另一种原因是内存管理器需要频繁回收内存页,这也会产生一定的CPU消耗。所以如果有大批量key过期,要给过期时间设置一个随机范围。

# 在目标过期时间上增加一天的随机时间
redis.expire_at(key,random.randint(86400)+expire_ts)

从节点的过期策略

    从节点不会进行过期扫描,从节点对过期的处理是被动的主节点在key到期时,会在 AOF 文件里增加一条del指令同步到所有从节点,从节点通过执行这条del指令来删除过期的key。
    因为指令同步是异步进行的,所以如果主节点过期的key没有及时同步到从节点的话,就会出现主从数据的不一致,主节点没有的数据在从节点里还存在。

Redis提供两种方式持久化:
1.RDB,将Redis在内存中的数据库记录定时dump到磁盘
2.AOF,将Redis的操作日志以追加的方式写入文件。

你可能感兴趣的:(Redis,redis)