使用 C 语言开发的数据库,不过与传统数据库不同的是 Redis 的数据是存在内存中,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。除了缓存之外,Redis 也经常用来做分布式锁,甚至是消息队列。
1.特点:
- 高性能:内存操作速度快
- 高并发:相对于普通数据库能支持更高的并发度
- 丰富的数据类型:相对于memcached所支持的数据类型更多
- 持久化:有rdb,aof这些持久化机制
- 部分支持事务:使用Lua脚本可以让一组命令原子执行、
- 支持数据备份:master-slave模式数据备份
2.性能高的原因
- 纯内存操作
- 单线程操作,避免频繁上下文切换,(操作简单,不需要多线程加持)
- 采用非阻塞I/O多路复用机制,事件被多路复用程序放入队列中,然后事件分派器依次去队列中取,转发到不同的事件处理器中。 redis还提供了select、epoll、evport、kqueue等多路复用函数库。reacter模式。
3.数据类型
- string 字符串或者数字,复杂计数功能缓存 get set strlen exist del
- hash 结构化对象,操作其中某个字段,单点登录可以用其保存用户信息,以cookieId作为key,设置缓存过期时间,模拟出类似session的效果 hset和hget 先压缩表,元素过多时hashtable
- list 消息队列功能,使用lrange命令,做基于redis的分页功能 lpush lpop rpush rpop lrange lindex blpop brpop
- set 集合,全局去重,利用交并补计算共同喜好、全部喜好、独有喜好等。 sadd srem
- zset 多了一个权重score,排行榜,取top N,延时任务,范围查找等。 底层先使用压缩表,当元素过多时跳表实现
- bitmap 保存连续二进制数,节省空间,非核心了。。
- Streams 功能强大,支持多播,可持久化的消息队列
渐进式Rehash
当哈希表存储巨大数量键值对,如果一次rehash,可能宕机
步骤:
- 为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表
- 维持索引计数器比那两rehashidx,设为0,表示开始
- 每次对字典增删查改,ht[0]的rehashidx索引上的所有键值对rehash到ht[1],将rehashidx值+1。
- 当全部键值对移动完成,rehashidx设置为-1,表示操作完成
这样避免了集中rehash大计算量造成问题,将计算均摊到每个字典增删查改操作。
4.应用场景
- 排行榜 zset
- 计数器 string类型的原子自增操作
- 好友关系 利用集合交并补
- 简单消息队列 list自带机制
- session共享
- 分布式锁
5.数据过期策略和淘汰机制
5.1.过期策略
过期字典(hash表),key为数据库的键,value是long long类型整数,保存了key指向的数据库键的过期时间。
- 惰性删除:当访问key才判断是否过期,节省CPU对内存不友好。
- 定期删除:每100ms抽取部分数据进行删除,漏掉的数据在用到的时候惰性删除,折中内存和CPU。
过期的贪心策略:
- 从过期字典中随机选择20个key;
- 删除这20个key中已过期的key;
- 如果已过期key的比例超过25%,则重复步骤1。
5.2.内存淘汰机制
如果数据一直没有被选择清除掉,而且也