之前遇到过个用户,平时不忒管闲事,今天非要入坑,非要问我 Redis 如何设值。我本来想略微调个皮,让代码里好办点,但一问到原理,我直接急了,脑子里全堆了那些标准教材里那些像念经一样的“起初、其次、最终”啊。
后来我算了算,还是得把那些花里胡哨的铺垫给扔了,直接跟你说说这玩意儿到底是个啥操。 Redis 设值这事儿,拿个比喻来说最顺。你能够把它想象成你在办公室墙上的便利贴。
你想在墙上贴个“待办事项”,你就把便利贴贴上去了。
这时候,你贴上去的动作,在内存里就对应了一次操作。
可是,要是这墙挺脏,要么你贴的时候没把名字写上,那这贴上去的动作想不消亡都不中。并且,墙上的字,你要是用红色记号笔写了,别人看到就知道是你亲自动的手;要是用黄色记号笔写了,那可能是哪位干的哪位就不清楚。
这就叫 key 和 value 的关系,key 就是那面墙,value 就是贴在那里的纸条,value 里的字段值就是那记号笔的颜色。 实际上说得更直白点,Redis 设值就是给一个 ID(Key)贴一张纸(Value),这张纸还得带上颜色(数据类型)。
要是这张纸只是干巴巴的白纸,那它就没啥用。
要是给了颜色,比如用 Key-Value 这种组合,那赶明儿哪位都能一眼看出来哪位贴的、贴的是啥。
要是给颜色还加了个指纹,比如用 Timestamp,那还能知道这纸条是啥时候贴上去的。 大量人一听到 Redis,第一反应就是那种深不可测的底层机制,内存分配、链表结构、多路复用这些,听得我脑子直冒汗。
实际上别把重点放在那些复杂的底层结构,那样好办把人吓跑。Redis 设值这事儿,说白了就是利用内存的高速特性,把数据存有一块地方,然后随时读出来。就跟你在手机上存个微信,回车键一按,数据瞬间到你脑海里一样快。你不用管数据在物理世界里如何被搬运的,你只关心它能不能被你取出来,能不能被快速写进去。 我记得有个用户,第一次来问这玩意儿,说怕压死内存。我跟他讲,如何怕?就就像你在地下室里存放一堆书,万一你把书全扔进脏水里,那书不就烂了吗?Redis 的底层确实是一个个小的内存单元,但那个单元本身是专门用来存数据的,故此它不怕脏。自然,脏是不怕,但要是把脏东西塞进去,系统就得停下来要么报错。
这就对应到 Redis 里的 set 命令,它有个参数叫 maxmemory,就是设定一个内存的上限。
比如你设定上限是 100MB,那你往这 100MB 里塞数据,一旦塞满了,Redis 就会停下来,告诉你要释放内存了。
这时候你要是还想加,那就要先把旧的数据删了,要么压缩它,要么直接在磁盘上写点备份文件,要么就直接删掉,反正不能让这 100MB 装得下更多了。 还有个事儿,就是数据类型。你说你设个值,是设个字符串,还是设个数字,还是设个列表?这得看你想干嘛。
要是你只想存个名字,那用 set 是个字符串。
要是你想存个整数,比如库存数量,那用 set 存个数字也行。
要是你想存个工夫,那用 set 存个带工夫戳的字符串也行。Redis 里实际上有一种底层结构叫 list,出于它底层就是个链表,存起来特别快,适合存那种顺序的数据。
比如你要存一个签到顺序,用 list 就挺合适。
可是,set 命令本质上是个 key-value 的集合,它精通存那些无序的、需求快速查找的数据。 比如你想存个商品列表,商品 A、商品 B、商品 C,你把这三个都设进去。
这时候,Redis 内部维护着一个键值对。
第一个商品,它的 key 是 "item_001",value 是商品 A 的信息;第二个商品,key 是 "item_002",value 是商品 B 的信息。
这时候你又想加个商品 D,key 变成 "item_003",value 是商品 D 的信息。
这三个 key 放在一起,Redis 就能一眼认出它们都是商品,别看它们散落在不同的地方,但逻辑上是连在一起的。你要是要查这个商品在哪,要么要取这个商品的信息,Redis 就会去翻那个对应的 key 里的 value。 这过程确实有点绕,但益处是内存占用小。出于 Redis 的内存是动态分配的,你只需求存数据,别管如何存。
不像文件系统强制你得有文件结构,要么数据库得有特定的索引结构。Redis 准你存那些看似毫无意义的垃圾数据,只要你设置得对,系统就能自动处理。
比如你存了一个庞大的二进制文件,Redis 内部会把它当成一个字符串存起来,只要不超过内存限制,它就能存下。
这就叫数据载体灵活。 还有一种情况,就是当数据量确实忒大了,超过了内存,Redis 就得去读盘了。
这时候,Redis 会把内存里的数据写入到磁盘上,这时候它就像一个一般/平平的文件操作,KV 写入,KV 读取。
不过,这时候速度会变慢,出于磁盘读写比内存快不了多少。
故此,这得看你的场景,要是你的数据量在几十万条以内,用内存存彻底没难题,速度是秒级的。
要是是几十万条以上,启动占用磁盘了,那速度就能维持在毫秒级,还是挺快。 还有个细节,就是内存管理。Redis 有个叫 eviction 的机制,实际上就是淘汰策略。当内存满了,它得拍板把哪个数据删掉,要么把哪个数据压缩。常见的策略有 LFU(最久未使用的键淘汰)、LRU(最近最少使用的键淘汰)、ALL(全体删除)、VACUUM(清理空键)。
比如你存了三年没用的数据,Redis 可能会把它删掉,释放出内存空间给新的数据用。
这就叫内存优化。 我上次在处理一个用户时,他问我这玩意儿会不会有死锁。我说死锁一般形成在多线程竞争资源上,而 Redis 是单线程模型,故此理论上不会死锁。
可是,要是是多个线程与此同时往同一个 key 上写数据,那可能会形成竞态条件,到时候数据就乱套了。
故此,还是得做好数据同步,要么用 Redisson 这种分布式锁来保证线程保险。 总的来说,Redis 设值这事儿,就是把它当成一个内存里的字典来用。你定义一个 key,里面放个 value,然后随时查。它贼高效,内存占用也低,数据类型也灵活。别看底层有点复杂,但用好了,就是内存里的一个一般/平平 SQLite 要么 MySQL,只不过它更快,更灵活。对于新手来说,别整那些复杂的调优,先把能用的功能用好了,那就是王道。数据是你想要的,内存是你给的,把这两者匹配好,Redis 设值这事儿就赚翻了。