redis 简介
是有全称的,key value数据库。
简单理解:客户端和服务端通过resp协议(tcp\socket)来实现通信。控制了单线程,存在内存中的键值对结构的数据。
最大的优点:快 为什么快:
-
内存(最主要的原因),
-
C开发(接近系统)
-
单线程(无线程上下文切换,使用IO多路复用模型(计算机底层知识)、epoll机制)
-
代码写的好: 针对不同的数据库结构和大小,有不同的内部编码(即算法),节省内存和提高效率
-
协议简单(resp协议)
使用场景
这个熟悉redis的特性就自然知道了。(由于数据结构的设计,延伸了很多功能)。下面罗列主要是string类型的使用。
- 缓存 保存临时数据 、热数据
- 比如 排行榜()、社交的点赞等 计数器(自增incby)、
- 分布式锁(setnx命令+结合lua):github.com/redisson/re… 官方实现
- 分布式ID等等
- 秒杀
- 共享session:因为session的信息很小,所以可以不存很多很多session。实践spring-session
- 限速:类似令牌桶guava的RateLimiter
- 根据API及特性 自增、超时等,自由发挥。
不适用的场景
- 海量数据:内存比起硬盘还是差2个数量级的;
- 对并发、性能要求不高的(引入毕竟有成本,开发成本、数据一致性等。没有秒杀、抢购、几百万用户的,几乎不用考虑。就比如你要去周边城市,开个车就好了,没必要坐飞机、开飞机)
- 单线程决定了,每个命令的执行不能太耗时,负责阻塞。(所以对redis的值的大小有个<512M的限制,尽量避免百M的数据)
协议
内部编码的转换及选择
内部编码会根据数据的具体大小等自动转换编码,很耗时。 那类比java jdk 的hash的put的扩容, 最佳实践(可能):自己写一个redis的client,根据key的数量及value的大小等选择对应的内部编码。 减少(不是避免)扩容的操作。
string 字符串
int: 8byte embstr:=<39 raw: >39
使用场景:
会根据值的类型和大小选择。
hash 哈希
- ziplist(压缩列表):顾名思义,空间连续,内存占用少数据量或者值小
- hashtable(散列表表):尽量避免 ziplist到hashtable的自动转换(客户client可以根据filed的数量指定内部编码)
使用场景
优点(对比hash),减少键的数量; 保存的一个map对象。不同的key,各自的map是不一样的(废话๑乛◡乛๑)。
列表
有序-->队列 编码转换 ziplist-->hashtable --> quicklist
使用场景
有分页列表的功能,比如好友头像列表,新闻标题列表
set 集合
- 类似java jdk set,无重复、无序的。
- 既然是集合,那就有初中数学的知识,集合的交、并、补等运算。 然后延伸的功能:
- 共同好友(wx公共号的在看)、通过的爱好(标签)
intset(数据量少) --> hashtable(数据量多)
zset 有序集合
和set比有序,整个有序的规则(依据):分数。 排行榜功能。比如签到奖励排名、消费排名、热度排名、中奖排名等的
ziplist(数据量少) --> skiplist(数据量多)
bitmaps 位
相比较hash,占用空间少(热数据) 也有集合的预算。 使用场景,比如:每天 用户是否登录过、那些天是否登录过
优化
api级别:
- mXX批处理命令:
- pipeline: