关于 Redis

写在前面

只有回过头来,才能理解生活。——欧洲谚语

Antirez 是 Redis 的作者,由于他的父亲是一名电工,会自己编程一些程序来解决工业自动化相关的问题,这也让 Antirez 对计算机编程从小就有了认识。

2007 年 Antirez 创立了 LLOOGG 网站,主要是用于网站分析这一块。一开始他使用 MySQL 做存储,但发现有很严重的性能问题。思前想后,他决定直接借助内存,在其上编写一个数据库,叫 LMDB(LLOOGG Memory Database),这个就是 Redis 的前身。

在这个 LMDB 里,就开始有了 SET、GET、LPUSH、RPUSH 等基本指令,并且有 string 和 list 两种类型可以使用。

2 年后,Redis 在 Hacker News 上做了公开,但那个时候还无人问津,但这不影响到 Antirez,他还是利用工作之余开发 Redis,不断地完善它,慢慢地它的用户量开始有所增长。

随后,Github、Instagram、Twitter 等公司也加入使用 Redis 的行列,使得 Redis 达到了现在的热度。

我们都是站在巨人的肩膀上,别人过去的一个月可能是我们现在的十分钟。我们通过了解一些事物的过去的发展历史,也能让我们对这个事物能有更加全面的理解。每个事物发展到如今,都是有它的路子,而未来发展成怎样,就是今天继续走下去的每一步决定的。


内容

我确实认为一个好的思考框架是物理学的那种第一原则推理。我的意思是,把事情归结为基本的真理,然后从那里往上推理。 ——马斯克

由于 Redis 从一开始就是基于内存和单线程来设计的,这也就定下了基调,从它的数据结构、功能、应用、机制上等多方面的设计、优缺点等都可以看出来,很多都是围绕着内存和单线程这些物理属性来的。比方说 Redis 的数据类型为什么会设计成好几种,为什么一个数据类型下还要设计多种编码方式,为什么对键要有过期机制,为什么要有惰性删除,为什么可以成为分布式锁的应用等。

以内存方面为例,就好比 Redis 是一棵树,它的根叫内存,给上面的枝干树叶提供养分。键就是它的叶子,时间到了就要落下。枝干就是编码方式,枝干如果一直生长,就会越来越重,此时一开始它会自己分叉,相当于换编码方式,来满足生长。但如果再继续下去,就需要一些外部力量了,例如人工来修剪,相当于修改 redis 的配置或是外部调整 redis 对键的使用等。


内存

Redis 提供了五种数据类型,而每种数据类型,又会根据实际情况有不同的内部编码,最终的目的,也是为了整体在内存上的时间和空间的平衡问题。

key
string
hash
list
set
zset
raw
int
embstr
listpack
hashtable
quicklist
intset
hashtable
listpack
skiplist

比方说一个用户信息,我们可以用 string 对每个字段来存,也可以整个用 hash 来存。但往往我们会使用 hash,因为 string 需要对用户信息的每个字段做存储,意味着需要多个 key,就会占用更多的空间。如果说把该用户信息序列化,然后只用一个键来保存,那么也意味着会有反序列化的开销。而使用 hash 的话就能即用一个键来保存,又没有序列化的开销问题。

但使用 hash 的话,就需要注意存储的规模问题,也就是如果 hash 存储的是数量不多的小对象的时候,hash 会使用 ziplist 的内部编码实现,当超过了限制条件,为了保证读写效率,就会换成 hashtable,但这样就会占用更多的空间。

在这一点上,我们可以看到有两个变化点,一个是数据类型,一个是该数据类型下的内部编码。这也就意味着,在使用 Redis 的时候,有几个点可以让我们思考下:

  • 在面对某个场景的时候,哪种数据类型更加适合处理该问题?
  • 在该场景下,如果数据量超过了这个数据类型内部的一些边界条件,此时它会换一种内部编码,到时会怎样?

而这些变化的地方,又会引出以后我们做 Redis 优化的内容。
还是以上面的用户信息为例,为了避免 hash 性能问题发生,我要做的始终也是围绕 Redis 来做,要么就是修改 Redis 的配置,如hash-max-ziplist-entries和hash-max-ziplist-value参数。要么就是原来的配置不变,变的是我给 Redis 的内容,例如为了控制数量,我代码层面就不让它们存储在同一个 hash 里,而是手动分组出多个 hash 出来存等。

单线程

Redis 的单线程是从客户端发送指令到服务端处理指令,返回结果这个过程来说的,在对于其它部分,例如持久化、集群等,则是多线程处理。大多数时候,在我们做业务开发的时候,我们都能认为是在单线程的情况下。在以前,我们删除一个 bigkey 的时候,它会可能触发 redis 阻塞的情况,那个时候的一种处理方法是,使用 scan 获取 bigkey 的部分内容,逐步的删除,然后再删掉该 bigkey。后来 redis 对删除支持了异步的处理,我们可以使用 unlink 命令来代替原来的 del 命令。

参考

Redis 與作者 antirez 的故事
《Redis 开发与运维》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值