再谈redis

一、介绍一下Redis

Redis是一个开源的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。

从官方的解释上,我们可以知道:Redis是基于内存,支持多种数据结构。 从经验的角度上,我们可以知道:Redis常用作于缓存。

1.1为什么要用Redis?
从上面可知:Redis是基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。

我们可以发现这不就是Java的Map容器所拥有的特性吗,那为什么还需要Redis呢?

Java实现的Map是本地缓存,如果有多台实例(机器)的话,每个实例需要各自保存一份缓存,缓存不具有一致性
Redis实现的是分布式缓存,如果有多台实例(机器)的话,每个实例都共享一份缓存,缓存具有一致性。
Java实现的Map不是专业做缓存的,JVM内存太大容易挂掉的。一般用做于容器来存储临时数据,缓存的数据随着JVM销毁而结束。Map所存储的数据结构,缓存过期机制等等是需要程序员自己手写的。
Redis是专业做缓存的,可以用几十个G内存来做缓存。Redis一般用作于缓存,可以将缓存数据保存在硬盘中,Redis重启了后可以将其恢复。原生提供丰富的数据结构、缓存过期机制等等简单好用的功能。

参考资料:

为什么要用redis而不用map做缓存?https://segmentfault.com/q/1010000009106416

1.2为什么要用缓存?

如果我们的网站出现了性能问题(访问时间慢),按经验来说,一般是由于数据库撑不住了。因为一般数据库的读写都是要经过磁盘的,而磁盘的速度可以说是相当慢的(相对内存来说)

科普文:让 CPU 告诉你硬盘和网络到底有多慢https://zhuanlan.zhihu.com/p/24726196

在这里插入图片描述
如果学过Mybaits、Hibernate的同学就可以知道,它们有一级缓存、二级缓存这样的功能(终究来说还是本地缓存)。目的就是为了:不用每次读取的时候,都要查一次数据库。

有了缓存之后,我们的访问就变成这样了:
在这里插入图片描述

二、Redis的数据结构

Redis 命令参考:http://doc.redisfans.com/ try
Redis(不用安装Redis即可体验Redis命令):http://try.redis.io/

Redis支持丰富的数据结构,常用的有string、list、hash、set、sortset这几种。学习这些数据结构是使用Redis的基础!

首先还是得声明一下,Redis的存储是以key-value的形式的。Redis中的key一定是字符串,value可以是string、list、hash、set、sortset这几种常用的。
在这里插入图片描述
但要值得注意的是:Redis并没有直接使用这些数据结构来实现key-value数据库,而是基于这些数据结构创建了一个对象系统。

简单来说:Redis使用对象来表示数据库中的键和值。每次我们在Redis数据库中新创建一个键值对时,至少会创建出两个对象。一个是键对象,一个是值对象。
Redis中的每个对象都由一个redisObject结构来表示:

typedef struct redisObject{

    // 对象的类型
    unsigned type 4:;

    // 对象的编码格式
    unsigned encoding:4;

    // 指向底层实现数据结构的指针
    void * ptr;

    //.....


}robj;

简单来说就是Redis对key-value封装成对象,key是一个对象,value也是一个对象。每个对象都有type(类型)、encoding(编码)、ptr(指向底层数据结构的指针)来表示。

三、Redis中数据结构的对象

3.1字符串(stirng)对象
再次看回这张图,觉不觉得就很好理解了?
在这里插入图片描述
在上面的图我们知道string类型有三种编码格式:

int:整数值,这个整数值可以使用long类型来表示
如果是浮点数,那就用embstr或者raw编码。具体用哪个就看这个数的长度了
embstr:字符串值,这个字符串值的长度小于39字节
raw:字符串值,这个字符串值的长度大于39字节
embstr和raw的区别:

raw分配内存和释放内存的次数是两次,embstr是一次
embstr编码的数据保存在一块连续的内存里面
编码之间的转换:

int类型如果存的不再是一个整数值,则会从int转成raw
embstr是只读的,在修改的时候回从embstr转成raw

3.2列表(list)对象

在上面的图我们知道list类型有两种编码格式:

ziplist:字符串元素的长度都小于64个字节&&总数量少于512个
linkedlist:字符串元素的长度大于64个字节||总数量大于512个
ziplist编码的列表结构:

redis > RPUSH numbers 1 "three" 5
    (integer) 3 

在这里插入图片描述
linkedlist编码的列表结构:
在这里插入图片描述
编码之间的转换:

原本是ziplist编码的,如果保存的数据长度太大或者元素数量过多,会转换成linkedlist编码的。

3.3哈希(hash)对象

在上面的图我们知道hash类型有两种编码格式:

ziplist:key和value的字符串长度都小于64字节&&键值对总数量小于512
hashtable:key和value的字符串长度大于64字节||键值对总数量大于512
ziplist编码的哈希结构:
在这里插入图片描述

在这里插入图片描述
hashtable编码的哈希结构:
在这里插入图片描述
编码之间的转换:

原本是ziplist编码的,如果保存的数据长度太大或者元素数量过多,会转换成hashtable编码的。

3.4集合(set)对象

在上面的图我们知道set类型有两种编码格式:

intset:保存的元素全都是整数&&总数量小于512
hashtable:保存的元素不是整数||总数量大于512
intset编码的集合结构:
在这里插入图片描述
hashtable编码的集合结构:
在这里插入图片描述
编码之间的转换:

原本是intset编码的,如果保存的数据不是整数值或者元素数量大于512,会转换成hashtable编码的。

3.5有序集合(sortset)对象

在上面的图我们知道set类型有两种编码格式:

ziplist:元素长度小于64&&总数量小于128
skiplist:元素长度大于64||总数量大于128
ziplist编码的有序集合结构:
在这里插入图片描述
skiplist编码的有序集合结构:
在这里插入图片描述
有序集合(sortset)对象同时采用skiplist和哈希表来实现:

skiplist能够达到插入的时间复杂度为O(logn),根据成员查分值的时间复杂度为O(1)
编码之间的转换:

原本是ziplist编码的,如果保存的数据长度大于64或者元素数量大于128,会转换成skiplist编码的。
3.6Redis对象一些细节

(1:服务器在执行某些命令的时候,会先检查给定的键的类型能否执行指定的命令。
比如我们的数据结构是sortset,但你使用了list的命令。这是不对的,服务器会检查一下我们的数据结构是什么才会进一步执行命令
(2:Redis的对象系统带有引用计数实现的内存回收机制。
对象不再被使用的时候,对象所占用的内存会释放掉
(3:Redis会共享值为0到9999的字符串对象
(4:对象会记录自己的最后一次被访问时间,这个时间可以用于计算对象的空转时间。

我们在使用的时候挑选哪些数据结构作为存储,可以简单看看:

string–>简单的key-value
list–>有序列表(底层是双向链表)–>可做简单队列
set–>无序列表(去重)–>提供一系列的交集、并集、差集的命令
hash–>哈希表–>存储结构化数据
sortset–>有序集合映射(member-score)–>排行榜

转载自:Java技术公众号:Java3y
感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值