Redis有哪些数据类型?

其实根据Redis的官网给出的结果:Redis data types | Redis

Redis有以下数据类型:

序号英文中文是否基本数据类型简介
1String字符串最基本的数据类型,用于存储字符串、整数或浮点数。
2Lists列表一组有序的元素,可以在头部或尾部添加元素,适用于存储有序的元素集合。
3Sets集合一组无序的元素,可以进行交集、并集、差集等操作。
4Hashes哈希表一种键值对的集合,适用于存储对象。
5Sorted sets有序集合(Zset)一组有序的元素,每个元素都有一个分值,可以按照分值排序和范围查询。
6Streams一种类似于消息队列的数据结构,可以进行发布和订阅操作。
7Geospatial地理位置一种存储地理位置信息的数据结构,可以进行地理位置相关的操作。
8Bitmaps位图一种特殊的字符串,可以进行位运算,用于存储二进制数据。
9Bitfields位域允许设置、递增和获取任意位长度的整数值。
10HyperLogLog基数统计一种基于概率算法的数据结构,用于统计元素的数量。

关于Redis的几个问题。

Redis为什么快?

  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap。而HashMap的优势就是查找和操作的时间复杂度都是O(1)。
  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU资源,不用去考虑各种锁问题,不存在加锁释放锁操作,不可能出现死锁而导致的性能消耗。
  • 使用多路I/O复用模型,非阻塞I/O。
  • 使用底层模型不同,他们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM机制(虚拟内存机制)。因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

总之,Redis剪去了所有在操作上需要花费时间的机制。而且还使用了I/O速度更快的内存、使用了最快的查找和操作算法。

Redis的持久化机制是什么?各自的优缺点?

Redis提供两种持久化机制:

  • RDB(默认)
  • AOF机制。

RDB:是Redis DataBase缩写快照,是Redis的默认持久化方式。按照一定的时间周期将内存的数据以快照的形式保存到硬盘中,产生对应的数据文件dump.rdb。可以通过配置文件中的save参数来定义快照的周期。

优点:

  • 只有一个文件 dump.rdb,方便持久化。
  • 容灾性好,一个文件可以保存到安全的硬盘。
  • 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能。
  • 数据集较大时,比AOF的启动效率更高。

缺点:

  • 数据安全性低,RDB是间隔一段时间进行持久化,如果持久化之间Redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候

AOF:即Append Only File,是将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复

优点:

  • 数据安全,AOF持久化可以配置appendfsync属性,有always,每进行一次命令操作就记录到AOF文件中一次。
  • 通过append模式写文件,即使中途服务器宕机,可以通过Redis-checkaof工具解决数据一致性问题。
  • AOF机制的rewrite模式。AOF文件没被rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)。

缺点:

  • AOF文件比RDB文件大,且恢复速度慢。
  • 数据集较大的时候,启动比RDB效率低。

Redis的内存淘汰机制有哪些?

Redis中的内存淘汰机制包括三种:

  • 定期删除:Redis可以设置一个定时器,定期扫描键空间中的键,并删除已经过期的键。
  • 惰性删除:当一个键过期时,Redis不会立即删除该键,而是等到该键被访问时再删除。
  • 内存淘汰策略:当 Redis 内存占用达到上限时,会根据内存淘汰策略来选择一些键进行删除,以腾出更多的内存空间。

Redis的内存淘汰策略有哪些?

Redis的内存淘汰策略是指在Redis用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。

  • noeviction,不进行淘汰,但执行写入操作会报错。
  • allkeys-lru,在键空间中,移除最近最少使用的key。这里全部的key都使用LRU算法淘汰(Least Recently Used,最近最少使用),这个也是最常用的。
  • allkeys-lfu(在Redis4.0后新增),在键空间中,移除一定时间内使用次数最少的key。这里全部的key都使用LFU算法淘汰(Least Frequently Used,使用频率最低)
  • allkeys-random,在键空间中,随机移除某个key。
  • volatile-lru,在设置了过期时间的键空间中,移除最近较少使用的key。
  • volatile-lfu(在Redis4.0后新增),在设置了过期时间的键空间中,移除使用频率较低的key。
  • volatile-random,在设置了过期时间的键空间中,随机移除某个key。
  • volatile-ttl,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

Redis的内存淘汰策略的选取并不会影响过期key的处理。内存淘汰策略只被用于处理内存不足时需要申请额外空间的数据。而过期策略被用于处理过期的缓存策略。

如何解决Redis的并发竞争Key问题?

所谓的Redis的并发竞争Key的问题,其实就是多个系统同时对一个Key进行操作。但是,执行后的顺序和我们期望的顺序可能会不一样,这也导致了结果的不同。(优点类似事物ACID中的隔离性,交叉执行而导致数据的不一致。)

解决方法有两种:

  • 分布式锁(zookeeper 和 Redis 都可以实现分布式锁)。但如果不存在Redis的并发竞争Key问题,不要使用分布式锁,这样会影响性能。
  • 消息队列,把所有操作写入同一队列里,利用消息队列把所有操作串行化。

基于zookeeper临时有序节点可以实现的分布式锁。每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。然后判断一下是否获取锁,判断获取锁也很简单,只需要判断有序节点中序号小的那一个。当释放锁时,只需将这个瞬时节点删除即可。同时也能避免服务宕机导致的锁无法释放,而产生的死锁问题。业务流程走完之后,删除对应的子节点释放锁。