redis小于等于39字节的字符串是embstr编码,大于39是raw编码的原因:Redis是一个高性能的键值数据库,对于每个字符串对象都要尽可能地减小内存占用并提高访问速度,因此,Redis在不同场景下使用不同的编码方式,以实现优化。
一、redis小于等于39字节的字符串是embstr编码,大于39是raw编码的原因
Redis设计时考虑到了内存使用效率和CPU效率之间的平衡。因为Redis是一个高性能的键值数据库,所以对于每个字符串对象都要尽可能地减小内存占用并提高访问速度,同时又要尽可能地减少CPU消耗。
因此,Redis选择了两种不同的编码方式,在不同场景下使用不同的编码方式,以实现优化。
当字符串长度小于等于39字节时,Redis使用embstr编码,其主要原因如下:
- embstr编码可以减少内存碎片:因为短字符串很常见,指向一个连续的字符数组比指向一块连续内存的指针更加紧凑。
- embstr编码可以降低CPU消耗:因为处理较小的字符串时发生的操作次数更少。
- embstr编码也可以节省一些内存:因为这种编码方式不需要分配sds结构体。
而当字符串长度大于39字节时,Redis使用raw编码,其主要原因如下:
- raw编码可以避免浪费内存:如果直接采用embstr编码,字符串对象的内存空间可能会在后续操作中被重新分配,导致内存浪费。
- raw编码可以处理更长的字符串:过长的embstr编码字符串可能会导致内存碎片。
综上所述,Redis中使用两种不同的编码方式主要是为了平衡内存和CPU的性能,并在不同的场景下获得更好的性能。
Redis的embstr编码方式和raw编码方式以39字节为分界是在3.0版本之前,而在3.2版本之后,变成了以44字节为分界,也就是说,如果一个字符串值的长度小于等于44字节,则按照embstr进行编码,否则按照raw进行编码。出现这种变化是因为,针对短字符串的embstr使用最小的sdshdr8,而sdshdr8与之前的sdshdr相比正好减少了5个字节(sdsdr8 = uint8_t * 2 + char = 1*2+1 = 3, sdshdr = unsigned int * 2 = 4 * 2 = 8),所以其能容纳的字符串长度增加了5个字节变成了44。
二、Redis简介
1、概述
在我们日常的Java Web开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。
2、NoSQL 技术
为了克服上述的问题,Java Web项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。Redis和MongoDB是当前使用较广泛的NoSQL,而就Redis技术而言,它的性能十分优越,可以支持每秒十几万此的读/写操作,其性能远超数据库,并且还支持集群、分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中,更让人欣慰的是它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性。
3、Redis 在 Java Web 中的应用
Redis 在 Java Web 主要有两个应用场景:
- 存储缓存用的数据;
- 需要高速读/写的场合使用它快速读/写。
4、缓存
在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。
如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样速度明显就会快上不少,并且会极大减小数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用 Redis 存储一些常用和主要的数据,比如用户登录的信息等。
一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:
- 业务数据常用吗?命中率如何?如果命中率很低,就没有必要写入缓存;
- 该业务数据是读操作多,还是写操作多?如果写操作多,频繁需要写入数据库,也没有必要使用缓存;
- 业务数据大小如何?如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没有必要。
在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它。
从上面的分析可以知道,读操作的可能性是远大于写操作的,所以使用 Redis 来处理日常中需要经常读取的数据,速度提升是显而易见的,同时也降低了对数据库的依赖,使得数据库的压力大大减少。
5、高速读/写的场合
在如今的互联网中,越来越多的存在高并发的情况,比如天猫双11、抢红包、抢演唱会门票等,这些场合都是在某一个瞬间或者是某一个短暂的时刻有成千上万的请求到达服务器,如果单纯的使用数据库来进行处理,就算不崩,也会很慢的,轻则造成用户体验极差用户量流失,重则数据库瘫痪,服务宕机,而这样的场合都是不允许的。
所以我们需要使用 Redis 来应对这样的高并发需求的场合,具体步骤为:
- 当一个请求到达服务器时,只是把业务数据在 Redis 上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速响应的需求;
- 但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完 Redis 的读/写之后,会去判断该高速读/写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为0时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将 Redis 的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。
延伸阅读1:Redis 优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe,通知,key过期等等特性。