简介
Redis的数据库,完全基于内存,以字典(即键值对)形式进行存储,底层实现是哈希表,查找和操作的时间复杂度是O(1)。Redis是用C语言实现的,采用单线程,避免不必要的上下文切换,不用考虑锁的问题。使用多路I/O复用模型(非阻塞IO)。
数据结构
Redis数据以键值的形式存储,键是字符串对象,键的值则有五种数据类型(字符串、列表、哈希、集合、有序集合)。
- 字符串 String
常用函数:strlen、set、get、mset、mget、incr、decr
存储结构:字符串
场景:计数
- 散列 Hash
常用函数:hset、hget、hmset、hmget、hgetall、hexists、hdel、hkeys、hvals
存储结构:哈希表(hashMap)
应用场景:实体对象,如用户信息
- 列表 List
常用函数:lpush、lpop、rpush、rpop、llen、lrange、lrem
存储结构:双向链表
应用场景:消息队列
- 集合 Set
常用函数:sadd、srem、smembers、sismembers、sdiff、sinter、sunion、scard
存储结构:值为空的HashMap
应用场景:分类,如国家、地域、车型等
- 有序集合 SortedSet
常用函数:zadd、zrem、zrange、zrangebyscore、zscore、zcard
存储结构:跳跃表(skipList)
应用场景:排序
跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
持久化
- RDB
原理:在一定条件下,写入文件一次,无法秒级持久化。
实例:save 900 2 (900秒内有超过2个键值被修改,就写入文件一次)
优点:恢复数据的速度远快于AOF。
缺点:存在数据丢失的可能。
- AOF
原理:每次数据更新都记录下来,然后写入磁盘。
策略:always,每次都同步,直到数据同步到硬盘才返回,保证了数据完整性,但严重影响性能;
everysec,每秒同步一次,先将数据写入缓冲区,然后每秒写入磁盘一次,推荐使用;
no,同步时机完全由OS决定,数据不安全,易丢失,不推荐使用。
优点:持久化实时性高,不易丢数据。
缺点:文件体量大恢复数据时间长。
集群
Redis 3.0版本开始正式引入的集群功能,Redis 5.0更是在集群原有功能的基础上进一步添加了更多新功能,并且对原有功能做了很多优化,使得整个集群系统更简单、易用和高效。
Redis集群与单机版一样,也提供主从复制功能。Redis集群中的主节点(master node)负责处理客户端发送的读写请求,从节点(slave node)负责对主节点进行复制。
集群的好处或设计初衷是扩展Redis读写性能。除复制功能之外,Redis集群还提供类似于单机版Redis Sentinel的功能,以此来为集群提供高可用特性。集群中的各个节点将互相监视各自的运行状况,在某个主节点下线时,提升该节点的从节点为新主节点来继续提供服务。
消息队列(轻量级)
Redis的列表可以实现轻量级的消息队列,但不能作为专业的消息队列组件使用。其特点是简单且实时性高,但由于其过于简单且并不十分可靠,所以只能用于业务不太复杂,且数据量不大的应用场景。
事务(功能较弱)
redis事务功能较弱,实际开发中很少遇到使用Redis事务的场景,Redis不支持事务回滚,且事务隔离级别没那么细,但简单恰恰维护了性能上的优势。
替代方案:Lua脚本可以实现Redis事务相关功能,并且功能要强大很多。
使用规范
- 键名
- 键名尽量简短,节省存储空间。
- 键名不要包含特殊字符,如引号、换行、空格等。
- 用业务名和表名作前缀,防止key冲突,如业务名:表名:id。
- value
- 限制数据大小,字符串控制在10kb以内;
- 限制元素个数,list、hash、set、zset元素个数不要超过5000。
- 尽量批量操作,可提高效率,但要注意控制批量操作的元素个数,500个以内,但也要看元素字节大小。
- 删除元素不要用del,使用hscan,sscan,zscan方式渐进式删除。
- 过期时间到会自动触发del,如果元素个数庞大,易出现阻塞,latency可查。
- 防止集中过期,尽量打散过期时间。
- 命令
- 禁止线上使用keys,flushall,flushdb等,可通过rename机制禁掉命令,或使用scan渐进式处理。
- 不要长时间使用monitor命令,必要时才使用。