2020-09-13 redis学习笔记

1.redis的key是顶层模型,它的value是扁平化的。Redis中,所有的value都是一个Object。

typedef struct redisObject { 
 unsigned [type] 4; 
 unsigned [encoding] 4; 
 unsigned [lru] REDIS_LRU_BITS; 
 int refcount; 
 void *ptr; 
} robj; 

(1)type:数据类型,就是我们熟悉的string、hash、list等。
(2)encoding:内部编码,其实就是本文要介绍的数据结构。指的是当前这个value底层是用的什么数据结构。因为同一个数据类型底层也有多种数据结构的实现,所以这里需要指定数据结构。
(3)REDIS_LRU_BITS:当前对象可以保留的时长。跟键的过期策略有关。
(4)refcount:对象引用计数,用于GC。
(5)ptr:指针,指向以encoding的方式实现这个对象的实际地址。


image.png

2.String,在Redis内部,String类型有两种底层存储结构。Redis会根据存储的数据及用户的操作指令自动选择合适的结构。

  • int:存放整数型
  • SDS:存放浮点、字符串、字节类型
SDS简单动态字符串,simple dynamic string

SDS的内部数据结构

typedef struct sdshdr { 
 // buf中已经占用的字符长度 
 unsigned int len; 
 // buf中剩余可用的字符长度 
 unsigned int free; 
 // 数据空间 
 char buf[]; 
} 

可见,底层是一个char数据。buf的最大容量是512M,里面可以放字符串、浮点数和字节。
为什么直接用数组?因为buf会有动态扩容和缩容的需求,那每次对字符串的修改都会导致重新分配内存,效率很低。
SDS扩容方案
当字符串长度小于1M时,扩容都是加倍现有的空间。如果超过1M,扩容时一次只会多扩容1M的空间。
3.list底层有两种数据结构:链表linkedlist和压缩列表ziplist。当list元素个数极少且元素内容不长时,采用ziplist实现,否则使用linkedlist。
链表
redis使用的链表是双向链表。
4.hash
hash的底层实现有两种实现:压缩列表和字典(dict)。
**字典
字典其实就是类似于java语言中的map。与java中的HashMap类似,redis底层也是使用散列表作为字典的实现,解决hash冲突使用的是链表法。
5.set
set存储的如果是整数类型,就直接使用整数集合intset。使用二分查找来辅助,不过插入的时候,由于要移动元素,时间复杂度是O(N)
6.zset
zset是可排序的set,与hash的实现类似,如果元素个数不多且不大,就使用压缩列表ziplist来存储。不过由于zset包含了score的排序信息,所以在ziplist内部,是按照score排序递增来存储的,意味着每次插入数据都要移动之后的数据。
7.总结:
redis对外暴露的是对象(数据类型),而每个对象都是用一个redisobject持有,通过不同的编码,映射到不同的数据结构,不同对象的底层可能使用同一种数据结构,比如压缩列表或字典。
string:int或dsd
list:ziplist或linkedlist
hash:ziplist或哈希表(hashtable)(内部结构dict类似java map)
set:intset或哈希表(hashtable)
zetset:ziplist或skiplist(跳跃表)
8.redis内存划分
(1)数据,这部分占用的内存会统计在used_memory中。Redis在存储对象时,不是直接将数据扔进内存,认识将数据包装成redisObject对象,底层存储有int、dsd、ziplist、hashtable、intset、skiplist等数据结构。
(2)进程本身运行需要的内存。redis主进程本身运行肯定需要占用内存,如代码、常量池等。除了主进程外,redis创建的子进程也会占用内存,如redis执行AOF、RDB重写时创建的子进程
(3)缓存内存。包括客户端缓冲区、复制积压缓冲区、AOF缓冲区等。
(4)内存碎片
9.redis快的原因:
(1)完全基于内存,绝大部分请求是基于纯粹的内存操作,非常快速。
(2)数据结构简单,对数据操作也简单。
(3)采用单线程,避免了不必要的上下文切换和竞争。
(4)使用多路I/O复用模型,非阻塞IO。
10.redis持久化数据和缓存怎么做扩容。
(1)使用切片集群扩容
(2)如果redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定就不能变化。否则的话(即redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有redis集群可以做到这样。
11.redis的过期键的删除策略:
(1)定时过期:每个设置过期时间的key都需要创建一个定时容器,到过期时间就会立即清除。虽然可立即清除过期数据,但会占用大量cpu资源处理过期数据,影响缓存的响应时间和吞吐量。
(2)惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。节省cpu资源,对内存不友好,极端情况可能出现大量过期key没有再次被访问,从而不被清除,占用大量内存。
(3)定期删除:每个一定时间,臊面一地你给数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。
15.redis的内存淘汰策略:
reids的内存淘汰策略是指在redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。
全局的键空间选择性移除
(1)noevictioin:当内存不足以容纳新写入数据时,新写入操作会报错。
(2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最少使用的key。(这个最常用)
allkeys-random:当内存不足以容纳写入数据时,在键空间中,随机移除某个key。
设置过期时间的键空间选择性移除
(1)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
(2)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
(3)volatitle-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key有限移除。
16.reid事务支持隔离性(Isolation)吗?
redis是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完事务队列中的命令为止。
17.redis事务保证原子性吗,支持回滚吗?
redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
18.哨兵模式的功能:
(1)集群监控:负责监控redis master和slave进程是否正常工作。
(2)消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
(3)故障转移:如果master node挂掉了,会自动转移到slave node上。
(4)配置中心:如果故障繁盛了,通知client客户端新的master地址。
19.哨兵核心知识:
(1)哨兵至少需要3个实例来保证自己的健壮性。
(2)哨兵+redis主从的部署架构,是不保证数据零丢失的,只能保证redis集群的高可用性。
(3)对于哨兵+reids主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行重组的测试和演练。
19.redis集群模式的工作原理以及redis的key如何寻址?分布式寻址都有哪些算法?了解一致性hash算法吗?
(1)redis cluster是一种服务端sharding技术,3.0版本开始正式提供。Redis Cluster 并没有使用一致性hash,而是采用slot(槽)的概念,一共分成16384(2^14)个槽。将请求发送到任意节点,接收到请求的节点会查询请求发送到正确的节点上执行。
(2)分布式寻址算法:

  • hash算法(大量缓存重建)
  • 一致性hash算法(自动缓存迁移) + 虚拟节点(自动负载均衡)
  • redis cluster的hash slot算法
    20.redis主从复制的核心原理
    (1)当从库和主库建立MS关系后,会向主数据库发送SYNC命令
    (2)主库接收到SYNC命令后,会开始在后台保存快照(RDB持久化过程),并将期间接收到的写命令缓存起来。
    (3)当快照完成后,主Redis会将快照文件和所有缓存的写命令发送给从Redis
    (4)从Redis接收到后,会将快照写入磁盘并加载到内存,并执行收到的缓存命令。
    (5)主redis每当接收到写命令就会将命令发送到从redis,从而保证数据的一致。
    21.zookeeper分布式锁的实现
    基于zookeeper临时有序节点可以实现的分布式锁。大致思想为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。完成业务流程后,删除对应的子节点释放锁。

在实践中,当然是从以可靠性为主。所以首推Zookeeper。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容