Redis知识点整理

优势

  1. 性能极高 – 内存操作,单线程,非阻塞I/O多路复用机制
  2. 丰富的数据类型 – String、List、Hash、Set 、ZSet
  3. 原子 – Redis的所有操作都是原子性的,单个操作是原子性的。
  4. 丰富的特性 – 支持 publish/subscribe, key 过期等等特性。

数据类型

string

  • 数字或者字符串的操作
  • 计数

list

  • 消息队列
  • lrange分页

hash

  • 存储结构化信息:用户信息,登录信息,业务信息等等

set

  • 全局去重
  • 利用交集并集差集等等进行计算结果

zset

sorted set多了一个权重参数score,集合中的元素能够按score进行排列。

  • 排行榜应用,取TOP N操作
  • 范围查找

底层数据结构

简单动态字符串(simple dynamic string)SDS

除了用来保存字符串以外,SDS还被用作缓冲区(buffer)AOF(持久化)模块中的AOF缓冲区

C 字符串 SDS
获取字符串长度的复杂度为O(N) 获取字符串长度的复杂度为O(1)
API 是不安全的,可能会造成缓冲区溢出 API 是安全的,不会造成缓冲区溢出
修改字符串长度N次必然需要执行N次内存重分配 修改字符串长度N次最多执行N次内存重分配
只能保存文本数据 可以保存二进制数据和文本文数据
可以使用所有库中的函数 可以使用一部分库中的函数

链表

顺序存储对象信息,有用于缓存链表长度的属性,在插入删除对象功能中有良好性能,避免环的产生。
列表键的底层实现之一就是链表

字典

key-value 存储方式,通过hash值计算,判断key的存储,当容量过大,会通过rehash重新分配字典大小

普通状态下的字典:


image.png

解决哈希冲突:在插入一条新的数据时,会进行哈希值的计算,如果出现了hash值相同的情况,Redis 中采用了连地址法(separate chaining)来解决键冲突。每个哈希表节点都有一个next 指针,多个哈希表节点可以使用next 构成一个单向链表,被分配到同一个索引上的多个节点可以使用这个单向链表连接起来解决hash值冲突的问题。如下:

image.png

image.png

在插入后我们可以看到,dictEntry指向了k2,k2的next指向了k1,从而完成了一次插入操作(这里选择表头插入是因为哈希表节点中没有记录链表尾节点位置)

Rehash

随着对哈希表的不断操作,哈希表保存的键值对会逐渐的发生改变,为了让哈希表的负载因子维持在一个合理的范围之内,我们需要对哈希表的大小进行相应的扩展或者压缩,这时候,我们可以通过 rehash(重新散列)操作来完成

  1. 目前的哈希表状态

我们可以看到,哈希表中的每个节点都已经使用到了,这时候我们需要对哈希表进行拓展


image.png
  1. 为哈希表分配空间

哈希表空间分配规则:

如果执行的是拓展操作,那么ht[1] 的大小为第一个大于等于ht[0].used*2的2的n次幂

如果执行的是收缩操作,那么ht[1] 的大小为第一个大于等于ht[0].used的2的n次幂
因此这里我们为ht[1] 分配 空间为8,

image.png
  1. 数据转移

将ht[0]中的数据转移到ht[1]中,在转移的过程中,需要对哈希表节点的数据重新进行哈希值计算
数据转移后的结果:

image.png
  1. 释放ht[0]

将ht[0]释放,然后将ht[1]设置成ht[0],最后为ht[1]分配一个空白哈希表:

image.png
  1. 渐进式 rehash

上面我们说到,在进行拓展或者压缩的时候,可以直接将所有的键值对rehash 到ht[1]中,这是因为数据量比较小。在实际开发过程中,这个rehash 操作并不是一次性、集中式完成的,而是分多次、渐进式地完成的。
渐进式rehash 的详细步骤:

1、为ht[1] 分配空间,让字典同时持有ht[0]和ht[1]两个哈希表
2、在几点钟维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash 开始
3、在rehash 进行期间,每次对字典执行CRUD操作时(增加只针对ht[1]),程序除了执行指定的操作以外,
还会将ht[0]中的数据rehash 到ht[1]表中,并且将rehashidx加一
4、当ht[0]中所有数据转移到ht[1]中时,将rehashidx 设置成-1,表示rehash 结束

采用渐进式rehash 的好处在于它采取分而治之的方式,避免了集中式rehash 带来的庞大计算量。

跳跃表

Redis 只在两个地方用到了跳跃表,一个是实现有序集合键,另外一个是在集群节点中用作内部数据结构

  1. 跳跃表是有序集合的底层实现之一

  2. 主要有zskiplist 和zskiplistNode两个结构组成

  3. 每个跳跃表节点的层高都是1至32之间的随机数

  4. 在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的对象必须是唯一的

  5. 节点按照分值的大小从大到小排序,如果分值相同,则按成员对象大小排序

整数集合

整数集合是集合建的底层实现之一,当一个集合中只包含整数,且这个集合中的元素数量不多时,redis就会使用整数集合intset作为集合的底层实现

  1. 整数集合是集合建的底层实现之一

  2. 整数集合的底层实现为数组,这个数组以有序,无重复的范式保存集合元素,在有需要时,程序会根据新添加的元素类型改变这个数组的类型

  3. 升级操作为整数集合带来了操作上的灵活性,并且尽可能地节约了内存

  4. 整数集合只支持升级操作,不支持降级操作

压缩列表

压缩列表(ziplist)是列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项要么就是小整数值, 要么就是长度比较短的字符串,那么Redis就会使用压缩列表来做列表键的底层实现。

  1. 压缩列表是一种为了节约内存而开发的顺序型数据结构

  2. 压缩列表被用作列表键和哈希键的底层实现之一

  3. 压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者整数值

  4. 添加新节点到压缩列表,可能会引发连锁更新操作,删除节点也可能会引发连锁更新

总结

  1. Redis 数据库中的每个键值对的键和值都是一个对象。

  2. Redis 共有字符串、列表、哈希、集合、有序集合五种类型的对象,每种类型的对象至少都有两种或以上的编码方式,不同的编码可以在不同的使用场景上优化对象的使用效率。

  3. 服务器在执行某些命令之前, 会先检查给定键的类型能否执行指定的命令, 而检查一个键的类型就是检查键的值对象的类型。

  4. Redis 的对象系统带有引用计数实现的内存回收机制, 当一个对象不再被使用时, 该对象所占用的内存就会被自动释放。

  5. Redis 会共享值为 0 到 9999 的字符串对象。

  6. 对象会记录自己的最后一次被访问的时间, 这个时间可以用于计算对象的空转时间

主从复制(哨兵)

原理

salve 启动成功连接到master后会发送一个sync命令,master接到命令后启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,进程执行完毕后,master将传送整个数据文件到slave,以完成一次完全同步,也就是全量复制,而slave服务在接收到数据后,存盘到内存中;master将新的修改命令依次传给slave,完成同步,此时为增量复制

只要重新连接master,一次完全同步(全量复制)将被自动执行

缺点

由于所有的写操作都在master上,然后同步更新到slave上,所以从master同步到slave 机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,slave机器数量的增加也会使得这个问题更加严重

哨兵模式

  1. 监控redis集群

  2. 如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端);

  3. 能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave(如果有超过一个slave的话)中的一个来作为新的master,其它的slave节点会将它所追随的master的地址改为被提升为master的slave的新地址。

  4. 哨兵为客户端提供服务发现,客户端链接哨兵,哨兵提供当前master的地址然后提供服务,如果出现切换,也就是master挂了,哨兵会提供客户端一个新地址。

  5. 支持集群

过期策略

redis采用的是定期删除+惰性删除策略

  • 定期
    定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

  • 定时
    用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key

  • 懒惰
    获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除

定期删除+惰性删除也仍然存在问题,如果定期删除没删除key,然后也没即时去请求key,也就是说惰性删除也没生效。这样下去redis的内存会越来越高。那么就应该采用内存淘汰机制。

内存淘汰机制

常用淘汰算法

  1. FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
  2. LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
  3. LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰

Redis提供的淘汰策略

  • noeviction:不进行置换,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回error
  • allkeys-lru:优先删除掉最近最不经常使用的key,用以保存新数据
  • volatile-lru:只从设置失效(expire set)的key中选择最近最不经常使用的key进行删除,用以保存新数据
  • allkeys-random: 随机从all-keys中选择一些key进行删除,用以保存新数据
  • volatile-random: 只从设置失效(expire set)的key中,选择一些key进行删除,用以保存新数据
  • volatile-ttl: 只从设置失效(expire set)的key中,选出存活时间(TTL)最短的key进行删除,用以保存新数据

持久化

Redis中数据存储模式

  1. cache-only:只做为“缓存”服务,不持久数据,数据在服务终止后将消失,此模式下也将不存在“数据恢复”的手段,是一种安全性低/效率高/容易扩展的方式;
  2. persistence:为内存中的数据持久备份到磁盘文件,在服务重启后可以恢复,此模式下数据相对安全

对于persistence持久化存储,Redis提供了两种持久化方法:

  1. Redis DataBase(简称RDB)
  2. Append-only file (简称AOF)

如果同时开启两种持久化,会优先加载AOF进行恢复

RDB持久化:默认开启

指定时间间隔进行快照存储

优点:使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能
缺点:RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候

  • save:服务器进程进行快照存储(阻塞)
  • bgsave:进行异步快照存储(派生子进程处理,非阻塞)
  • 异常恢复:redis-check-rdb
#dbfilename:持久化数据存储在本地的文件
dbfilename dump.rdb
#dir:持久化数据存储在本地的路径,如果是在/redis/redis-3.0.6/src下
启动的redis-cli,则数据会存储在当前src目录下
dir ./
##snapshot触发的时机,save    
##如下为900秒后,至少有一个变更操作,才会snapshot  
##对于此值的设置,
需要谨慎,评估系统的变更操作密集程度  
##可以通过save “”来关闭snapshot功能  
#持久化(以快照的方式) 策略(默认)
save 900 1       (15分钟变更一次)
save 300 10     (5分钟变更10次)
save 60 10000  (1分钟变更1万次)
##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,
“错误”可能因为磁盘已满/磁盘故障/OS级别异常等  
stop-writes-on-bgsave-error yes  
##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,
同时也意味这较小的文件尺寸以及较短的网络传输时间  
rdbcompression yes

AOF持久化:默认不开启

以日志的形式来记录每个写操作,将redis执行过的所有写指令记录下来(读操作不记录),只许追加但不可以改写文件,redis启动之初会读取改文件进行重新构建数据

  • AOF通过保存所有修改数据库的写命令请求来记录服务器的数据库状态
  • AOF文件中的所有命令都会以Redis命令请求协议的格式保存

优点:可以保持更高的数据完整性,如果设置追加file的时间是1s,如果redis发生故障,最多会丢失1s的数据(appendfsync—>everysec);且如果日志写入不完整支持redis-check-aof来进行日志修复;AOF文件没被rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)。

缺点:AOF文件比RDB文件大,且恢复速度慢,运行效率也比rdb慢。

重写机制

当超过阈值,则启动内容压缩,只保留最小指令集,可使用命令:bgrewriteaof

  1. 定义

AOF采用文件追加的方式持久化数据,所以文件会越来越大,为了避免这种情况发生,增加了重写机制

当AOF文件的大小超过了配置所设置的阙值时,Redis就会启动AOF文件压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof

  1. 原理

当AOF增长过大时,会fork出一条新的进程将文件重写(也是先写临时文件最后rename),遍历新进程的内存数据,每条记录有一条set语句。
重写AOF文件并没有操作旧的AOF文件,而是将整个内存中的数据内容用命令的方式重写了一个新的aof文件(有点类似快照)

  1. 触发机制

Redis会记录上次重写时的AOF文件大小,默认配置时当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发

auto-aof-rewrite-percentage 100  (一倍)
auto-aof-rewrite-min-size 64mb

持久化策略

  • appendfsync always (同步持久化,每次发生数据变更会被立即记录到磁盘,性能差但数据完整性比较好)
  • appendfsync everysec (异步操作,每秒记录,如果一秒钟内宕机,有数据丢失)
  • appendfsync no (将缓存回写的策略交给系统,linux 默认是30秒将缓冲区的数据回写硬盘的)
##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能  
##只有在“yes”下,aof重写/文件同步等特性才会生效  
appendonly yes  

##指定aof文件名称  
appendfilename appendonly.aof  

##指定aof操作中文件同步策略,有三个合法值:always(记录立即同步,性能较差) everysec(每秒同步,官方推荐) no(将缓存回写的策略交给系统,linux 默认是30秒将缓冲区的数据回写硬盘的),默认为everysec  
appendfsync everysec  
##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”  
no-appendfsync-on-rewrite no  

##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”  
auto-aof-rewrite-min-size 64mb  

##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。  
##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后  
##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。  
auto-aof-rewrite-percentage 100

比较

  • RDB与AOF同时开启 默认先加载AOF的配置文件
  • 相同数据集,AOF文件要远大于RDB文件,恢复速度慢于RDB
  • AOF运行效率慢于RDB,但是同步策略效率好,不同步效率和RDB相同

衍生数据结构

Bitmaps

一个以位为单位的数组,数组的每个单元只能存储0和1

在我们平时开发过程中,会有一些boolean型数据需要存取,比如用户一年的签到记录,签了是 1,没签是 0,要记录 365 天。如果使用普通的 key/value,每个用户要记录 365 个,当用户上亿的时候,需要的存储空间是惊人的。

为了解决这个问题,Redis 提供了位图数据结构,这样每天的签到记录只占据一个位,365 天就是 365 个位,46 个字节 (一个稍长一点的字符串) 就可以完全容纳下,这就大大节约了存储空间。

基本使用

  1. setbit
  2. getbit
  3. bitcount:统计指定位置范围内 1 的个数
  4. bitpos:查找指定范围内出现的第一个 0 或 1
  5. bitfield:多位操作,子命令(get/set/incrby)

HyperLogLog

HyperLogLog 提供不精确的去重计数方案,标准误差是 0.81%

案例:统计网站每个网页每天的 UV 数据?
常用解决方案是利用set集合进行去重,但是访问量巨大的时候,需要的存储空间也会相当惊人。
但是如果精确度要求不那么高,使用HyperLogLog可以省下相当大的空间。
网传HyperLogLog与集合结构的占用空间对比图:

数据类型 1天 1月 1年
set 80M 2.3G 28G
HyperLogLog 20K 600K 7M

基本使用

  1. pfadd:增加计数
  2. pfcount:获取计数
  3. pfmerge:将多个 pf 计数值累加,比如两个页面的统计结果合并

Geo

用数据库来算附近的人

GeoHash 算法

GeoHash 算法将二维的经纬度数据映射到一维的整数,这样所有的元素都将在挂载到一条线上,距离靠近的二维坐标映射到一维后的点之间距离也会很接近。当我们想要计算「附近的人时」,首先将目标位置映射到这条线上,然后在这个一维的线上获取附近的点就行了。

image.png

将整个地球看成一个二维平面,然后划分成了一系列正方形的方格,设想一个正方形的蛋糕摆在你面前,利用二刀法进行切割,二刀下去均分分成四块小正方形,这四个小正方形可以分别标记为 00,01,10,11 四个二进制整数。编码之后,每个地图元素的坐标都将变成一个整数,通过这个整数可以还原出元素的坐标,整数越长,还原出来的坐标值的损失程度就越小。

image.png

GeoHash 算法会继续对这个整数做一次 base32 编码 (0-9,a-z 去掉 a,i,l,o 四个字母) 变成一个字符串。在 Redis 里面,经纬度使用 52 位的整数进行编码,放进了 zset 里面,zset 的 value 是元素的 key,score 是 GeoHash 的 52 位整数值。

通过 zset 的 score 排序就可以得到坐标附近的其它元素 (实际情况要复杂一些,不过这样理解足够了),通过将 score 还原成坐标值就可以得到元素的原始坐标。

基本使用

  1. geoadd:携带集合名称以及多个经纬度名称三元组,注意这里可以加入多个三元组
127.0.0.1:6379> geoadd company 116.48105 39.996794 juejin
(integer) 1
127.0.0.1:6379> geoadd company 116.514203 39.905409 ireader
(integer) 1
127.0.0.1:6379> geoadd company 116.489033 40.007669 meituan
(integer) 1
127.0.0.1:6379> geoadd company 116.562108 39.787602 jd 116.334255 40.027400 xiaomi
(integer) 2
  1. geodist:用来计算两个元素之间的距离,携带集合名称、2 个名称和距离单位
127.0.0.1:6379> geodist company juejin ireader km
"10.5501"
127.0.0.1:6379> geodist company juejin meituan km
"1.3878"
127.0.0.1:6379> geodist company juejin jd km
"24.2739"
127.0.0.1:6379> geodist company juejin xiaomi km
"12.9606"
127.0.0.1:6379> geodist company juejin juejin km
"0.0000"
  1. geopos: 获取集合中任意元素的经纬度坐标,可以一次获取多个
127.0.0.1:6379> geopos company juejin
1) 1) "116.48104995489120483"
   2) "39.99679348858259686"
127.0.0.1:6379> geopos company ireader
1) 1) "116.5142020583152771"
   2) "39.90540918662494363"
127.0.0.1:6379> geopos company juejin ireader
1) 1) "116.48104995489120483"
   2) "39.99679348858259686"
2) 1) "116.5142020583152771"
   2) "39.90540918662494363"
  1. georadiusbymember:最为关键的指令,它可以用来查询指定元素附近的其它元素,参数非常复杂。
# 范围 20 公里以内最多 3 个元素按距离正排,它不会排除自身
127.0.0.1:6379> georadiusbymember company ireader 20 km count 3 asc
1) "ireader"
2) "juejin"
3) "meituan"
# 范围 20 公里以内最多 3 个元素按距离倒排
127.0.0.1:6379> georadiusbymember company ireader 20 km count 3 desc
1) "jd"
2) "meituan"
3) "juejin"
# 三个可选参数 withcoord withdist withhash 用来携带附加参数
# withdist 很有用,它可以用来显示距离
127.0.0.1:6379> georadiusbymember company ireader 20 km withcoord withdist withhash count 3 asc
1) 1) "ireader"
   2) "0.0000"
   3) (integer) 4069886008361398
   4) 1) "116.5142020583152771"
      2) "39.90540918662494363"
2) 1) "juejin"
   2) "10.5501"
   3) (integer) 4069887154388167
   4) 1) "116.48104995489120483"
      2) "39.99679348858259686"
3) 1) "meituan"
   2) "11.5748"
   3) (integer) 4069887179083478
   4) 1) "116.48903220891952515"
      2) "40.00766997707732031"

如果使用 Redis 的 Geo 数据结构,它们将全部放在一个 zset 集合中。在 Redis 的集群环境中,集合可能会从一个节点迁移到另一个节点,如果单个 key 的数据过大,会对集群的迁移工作造成较大的影响,在集群环境中单个 key 对应的数据量不宜超过 1M,否则会导致集群迁移出现卡顿现象,影响线上服务的正常运行。所以建议 Geo 的数据使用单独的 Redis 实例部署,不使用集群环境

集群

Codis(豌豆荚)

一整套缓存解决方案,包含高可用、数据分片、监控、动态扩态 etc。走的是 Apps->代理->redis cluster


image.png

Cluster(官方)

image.png

没有proxy, 数据分片之后, 可以访问集群中任意一个节点来确定要访问的数据在哪个节点, 是一种将存储和元数据管理放一起的设计, 实现较复杂, 出现问题不好排查, 在大规模集群+多地域情况下不适合, 因为会导致较高的网络通讯成本

Twemproxy(Twitter)

image.png

基于 Twemproxy 与 Codis 的 redis 集群方案比较

拓展

Scan VS Keys

两个命令都是遍历Redis所有key或者查找指定模式的key

keys

  1. 没有offset、limit参数,不能限制查询个数
  2. keys是遍历算法,复杂度O(n),数据量大的时候会导致redis卡顿

Scan

  1. 复杂度O(n),但是scan是通过游标分步进行,不阻塞
  2. 提供limit,可控制返回结果数
  3. 同keys一样,提供模式匹配
  4. 服务器不需要为游标保存状态,唯一状态是scan返回客户端的游标整数
  5. 返回结果可能重复,需要客户端去重
  6. 如果遍历过程中有数据修改,改动后的数据不保证同步
  7. 单次返回结果是空的,不表示遍历结束,而要看返回的游标值是否为0

缓存事件

缓存雪崩

即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致服务崩了

解决方案:

  1. 给缓存的失效时间,加上一个随机值,避免集体失效。

  2. 使用互斥锁,但是该方案吞吐量明显下降了。

  3. 双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点:

一:从缓存A读数据库,有则直接返回

二:A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。

三:更新线程同时更新缓存A和缓存B。

缓存穿透

即故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。

解决方案:

  1. 利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试

  2. 缓存空对象,设置过期时间

  3. 提供一个能迅速判断请求是否有效的拦截机制(布隆过滤器)

布隆过滤器:内部维护一系列合法有效的key,可以迅速判断出请求所携带的Key是否存在,如果不存在则直接返回。

缓存击穿

大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去

解决方案:

  1. 使用互斥锁

在根据key获得的value值为空时,先锁上,再从数据库加载,加载完毕,释放锁。若其他线程发现获取锁失败,则睡眠后重试。至于锁的类型,单机环境用并发包的Lock类型就行,集群环境则使用分布式锁( redis的setnx)

  1. 布隆过滤器( 当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。)

Redis VS Memcache

/ 数据类型 单Key限制 持久化 内存利用率 性能
Memcache key-value 1MB 使用简单的key-value存储的话,Memcached的内存利用率更高 可使用多核,100k以上的数据中,Memcached性能要高于Redis
Redis string/list/hash/set/sorted set 512MB 是(RDB/AOF) 采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached Redis使用单核,在存储小数据时比Memcached性能更高

你可能感兴趣的:(Redis知识点整理)