Redis
字符串 实现 使用SDS(简单动态字符串),SDS不仅可以保存字符串还可以保存二进制数据,获取长度的时间复杂度是O(1),SDS的API是安全的,比如拼接字符串不会造成缓冲区溢出,总的来说就是对数组封装,提供一系列方便操作的API。 字符串对象有三种编码:int、raw、embstr 整数:ptr从void*转换为long 短字符串(至于多短,每个redis版本不一样):分配一块连续空间保存redisObject和SDS 长字符串:分别为redisObject和SDS分配两个内存,redisObject.ptr指向SDS embstr如果要修改大小的话,只能重新分配空间。因此embstr实际上是只读的,当要修改embstr的长度,redis会先将其转换为raw再进行修改。 使用场景 缓存对象、常规计数(INCR)、分布式锁(SET-NX)、共享Session List 列表 List在使用上就是一个Deque双端队列,存字符串 实现 redis3.2之前:小列表使用压缩列表实现,大列表使用双向链表实现 redis3.2之后:使用quicklist实现 使用场景 消息队列: 保序:LPUSH+RPOP,但是RPOP需要轮询,浪费CPU性能,因此还提供了BRPOP阻塞式读取 处理重复:每条消息设置一个全局唯一ID,利用ID判断是否已经消费,List不会为消息生成ID,需要用户自己添加 保证可靠:BRPOPLPUSH,读取的同时将消息插入另一个List作为留存,如果用户处理消息时失败,下次从留存List重新读取 作为消息队列的缺点: 不支持消费者组 Hash 哈希 适合存储对象 实现 redis7.0之前:小Hash使用压缩列表,大Hash使用哈希表 redis7.0之后:小Hash使用listpack,大Hash使用哈希表 使用场景 缓存对象:一般可以用String+序列化存储对象,并将变化频繁的字段抽出来用Hash存储 Set 集合 实现 元素都是整数的小Set:整数集合 否则:哈希表 使用场景 点赞:保证每个用户只能点一次赞 共同关注(SINTER) 推荐关注(SDIFF) 抽奖(允许重复中奖SRANDMEMBER,不允许SPOP) 潜在风险:「并、交、差」的计算复杂度高,数据量大的情况下会阻塞redis。可以用从库进行计算,或交给客户端来自行处理,从而不阻塞主库 ZSet 有序集合 比Set多了一个score,按照score排序。ZSet不支持「差」运行 实现 redis7.0之前:小zset使用压缩列表,大zset使用跳表 redis7.0之后:小zset使用listpack,大zset使用跳表 使用场景 排行榜:score最大的前几个(ZREVRANGE),范围score内最小的前几个(ZRANGEBYSCORE) 电话排序:获取132、133开头的号码( ZRANGEBYLEX phone [132 (134 ),不要在分数不一致的 SortSet 集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因为获取的结果会不准确 BitMap 实现 String 使用场景 签到统计:比如一年的签到只需要365个bit 判断登陆态:用户ID作为offset,如果ID是连续的,5000 万用户只需要 6 MB 的空间(5000万位) ...