目录
Redis六种数据结构
SDS
SDS特点
quicklist
链表特点
intset
hasttable
ziplist
skiplist
Redis五种数据类型
String
常见命令
List
常见命令
数据结构
Set
常见命令
数据结构
什么时候使用intset
Sorted Set
常见命令
数据结构
Hash
常见命令
数据结构
什么时候使用ziplist
为什么Redis这么快
Redis过期删除策略
Redis淘汰策略
Redis持久化方式有哪些
RDB
AOF
Redis缓存可能存在问题
缓存击穿
解决方案
缓存穿透
解决方案
缓存雪崩
解决方案:
Redis高可用方案
Sentinel
Cluster
MOVE
ASK
发布与订阅
订阅
退订
发布消息
事物
事务的实现
WATCH
位数组
HyperLogLong
通过 object encoding key可以查看key的数据结构
127.0.0.1:6379> object encoding test"quicklist"
Redis中创建了一种名为简单动态字符串(Simple Dynamic String,SDS) 作为字符串的默认数据结构。
链表被广泛用于实现Redis各种功能,比如发布与订阅等;他的主要特点有:
Redis是一种高级的key-value非关系内存数据库,支持五种数据类型:
类型 | 简介 | 特性 | 场景 |
---|---|---|---|
String(字符串) | 二进制安全 | 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M | 缓存 |
Hash(字典) | 键值对集合,即编程语言中的Map类型 | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) | 存储、读取、修改用户属性 |
List(列表) | 链表(双向链表) | 增删快,提供了操作某一段元素的API | 1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列 |
Set(集合) | 哈希表实现,元素不重复 | 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 | 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 |
Sorted Set(有序集合) | 将Set中的元素增加一个权重参数score,元素按score有序排列 | 数据插入集合时,已经进行天然排序 | 1、排行榜 2、带权重的消息队列 |
String是Redis常用的数据类型,典型使用场景有 缓存对象、常规计数以及分布式锁
命令 | 作用 | 示例 |
set | 用于给指定的key 设置指定值 | 127.0.0.1:6379> set message "hello word" ex 1000 OK |
get | 获取指定key的值 | 127.0.0.1:6379> get message "hello word" |
incr | 自增 | 127.0.0.1:6379> incr number (integer) 2 |
incrby | 按照指定步长进行自增 | 127.0.0.1:6379> incrby number 3 (integer) 5 |
decr | 自减 | 127.0.0.1:6379> decr number (integer) 4 |
decrby | 按照指定步长自减 | 127.0.0.1:6379> decrby number 3 (integer) 1 |
strlen | 获取指定key的值的长度 | 127.0.0.1:6379> strlen message (integer) 10 |
append | 向指定key的值追加数据 | 127.0.0.1:6379> append message " redis" (integer) 16 127.0.0.1:6379> get message "hello word redis" 127.0.0.1:6379> |
getrange | 按照指定范围从指定key中获取数据 | 127.0.0.1:6379> GETRANGE message 0 5 "hello " |
setrange | 将字符串特定索引上的值设置为指定的数据 | 127.0.0.1:6379> set message "hello word" OK 127.0.0.1:6379> setrange message 6 "redis" (integer) 11 127.0.0.1:6379> get message "hello redis" |
列表在Redis中实现上不是使用数据而是使用链表。典型使用场景是消息队列
命令 | 含义 | 示例 |
lpush | 将一个或多个值插入到列表头 | 127.0.0.1:6379> lpush mylist "hello" (integer) 3 |
rpush | 将一个或多个值插入到列表尾部 | 127.0.0.1:6379> rpush mylist "hello" "word" "hello" "redis" (integer) 4 |
lpop | 移除并返回列表的第一个元素 | 127.0.0.1:6379> lpop mylist "hello" |
rpop | 移除并返回列表最后一个元素 | 127.0.0.1:6379> rpop mylist "redis" |
lindex | 通过索引获取元素 | 127.0.0.1:6379> lindex mylist 0 "hello" |
Llen | 返回列表长度 | 127.0.0.1:6379> llen mylist (integer) 3 |
linsert | 在列表的元素前后插入新元素,如果指定元素不存在则不执行任何操作,如果列表不存在时候视为空列表不执行任何操作 | 127.0.0.1:6379> lrange mylist 0 -1 1) "hello" 2) "word" 3) "hello" 127.0.0.1:6379> Linsert mylist after "hello" "redis" (integer) 4 127.0.0.1:6379> lrange mylist 0 -1 1) "hello" 2) "redis" 3) "word" 4) "hello" |
lrange | 返回列表中指定区间的元素 | 127.0.0.1:6379> lrange mylist 0 -1 1) "hello" 2) "word" 3) "hello" |
lrem | 根据参数count值移除列表中于参数value个数相等的元素 | 127.0.0.1:6379> lrange mylist 0 -1 1) "hello" 2) "redis" 3) "word" 4) "hello" 127.0.0.1:6379> lrem mylist -2 "hello" (integer) 2 127.0.0.1:6379> lrange mylist 0 -1 1) "redis" 2) "word" 127.0.0.1:6379> |
列表的数据结构为quicklist.
127.0.0.1:6379> rpush test "hello" "word" "test"(integer) 3127.0.0.1:6379> object encoding test"quicklist"
适合用于集合的交集、并集等操作,典型使用场景是朋友关系
命令 | 说明 | 示例 |
sadd | 向集合中添加一个或多个元素 | 127.0.0.1:6379> sadd numbers 1 3 5 (integer) 3 |
scard | 查询集合中元素的数量 | 127.0.0.1:6379> scard numbers (integer) 4 |
sismember | 判断指定值是否是在集合中 | 127.0.0.1:6379> sismember numbers unkown (integer) 1 |
srandmember | 随机返回一个或多个元素 | 127.0.0.1:6379> srandmember numbers 2 1) "unkown" 2) "5" |
spop | 移除并返回集合中的一个或多个随机元素 | 127.0.0.1:6379> spop numbers 1 1) "5" |
srem | 从集合中删除指定元素 | 127.0.0.1:6379> SREM numbers 1 (integer) 1 |
smemebers | 返回集合中所有元素 | 127.0.0.1:6379> SMEMBERS numbers 1) "unkown" 2) "3" |
集合对象的编码可以是intset或者是hashtable.
127.0.0.1:6379> sadd numbers 1 3 5
(integer) 3
127.0.0.1:6379> object encoding numbers
"intset"
127.0.0.1:6379> sadd numbers "unkown"
(integer) 1
127.0.0.1:6379> object encoding numbers
"hashtable"
127.0.0.1:6379>
当集合对象同时满足以下两个条件时使用intset
典型shi yong
命令 | 说明 | 示例 |
zadd | 将一个或多个元素及其分数值天价到有序集合中 | 127.0.0.1:6379> zadd testSet 1 "hello" 2 "world" (integer) 2 |
zcard | 返回有序集合中元素个数 | 127.0.0.1:6379> zcard testSet (integer) 2 |
zcount | 统计有序集合中指定分数区间的元素个数 | 127.0.0.1:6379> zcount testSet 1 2 (integer) 2 |
zrange | 返回有序集合中指定区间的成员 | 127.0.0.1:6379> zrange testSet 1 2 1) "world" 2) "bar" |
zrevrange | 倒叙返回有序集合中指定区间的成员 | 127.0.0.1:6379> ZREVRANGE testSet 1 2 1) "world" 2) "hello" |
zrank | 返回有序集合中元素的排名 | 127.0.0.1:6379> zrank testSet "world" (integer) 1 |
zincrby | 对有序集合中元素的分数自增指定步长 | 127.0.0.1:6379> ZINCRBY testSet 2 "world" "4" |
zrem | 删除有序集合中一个活多个元素 | 127.0.0.1:6379> zrem testSet "world" (integer) 1 |
zscore | 查询有序集合成员元素的分值 | 127.0.0.1:6379> ZSCORE testSet "hello" "1" |
有序集合编码可以是ziplist 或 skiplist.
命令 | 说明 | 示例 |
hset | 为哈希表中的字段赋值 | 127.0.0.1:6379> hset book name "Think in Java" (integer) 1 |
hget | 获取哈希表中指定字段的值 | 127.0.0.1:6379> hget book name "Think in Java" |
hmset | 同时保存多个key-value键值对 | 127.0.0.1:6379> hmset book "author" "unkown" "date" "2020" OK |
hmget | 通过获取多个指定字段的值 | 127.0.0.1:6379> hmget book "name" "author" 1) "Think in Java" 2) "unkown" |
hexists | 用户查询哈希表的指定字段是否存在 | 127.0.0.1:6379> HEXISTS book "dora" (integer) 0 127.0.0.1:6379> HEXISTS book name (integer) 1 |
hdel | 用于删除哈希表中一个或多个指定字段 | 127.0.0.1:6379> hdel book "date" (integer) 1 127.0.0.1:6379> hdel book "date" (integer) 0 |
hlen | 获取哈希表中键值对的个数 | 127.0.0.1:6379> hlen book (integer) 4 |
哈希对象的编码可以是ziplist或hashtable
当哈希同时满足以下两个条件时使用ziplist
不满足上述两个条件的都是用hashtable.
如果缓存没有设置过期时间或其他场景没有被过期策略删除,导致redis缓存使用达到一定阈值会触发redis淘汰策略。
1.volatile-lru 从设置过期时间的key中,移除最近最少使用的key
2.volatile-ttl 从设置过期时间的key中,移除最近将要过期的key
3.volatile-random 从设置过期时间的key中,随机选择key进行移除
4.allkeys-lru 从所有的key中,移除最近最少使用的key
5.allkeys-random 从所有的key中,随机选择key移除
6.noevication 不过期处理,直接抛出异常
redis支持RDB和AOF两种持久化方案
RDB持久化可以配置为定期执行,她的作用是将某个时间点上的数据库状态保存到RDB文件中,RDB文件是一个压缩到二进制文件,可以通过它恢复到某个时刻到数据库状态。由于RDB文件是保存在磁盘上的,即使Redis服务崩溃或退出,只要有RDB文件,就可以使用它来恢复还原数据。
SAVE命令会阻塞redis进程,直到RDB文件生成完毕,在进程阻塞期间,redis不能处理任何命令请求,着显然在生产环境中是不合适的。
BGSAVE 则是fork出一个子进程负责生产RDB文件,父进程继续处理命令请求不会阻塞进程
AOF 和 RDB 不同,AOF是通过保存redis服务器所执行的命令来记录数据库状态。AOF通过追加、写入、同步三个步骤来实现持久化
1.当AOF持久化处于激活状态、服务器执行写命令后,写命令会追加到aof_buf缓冲区的末尾
2.服务器每结束一个事件循环之前,会调用flushAppendOnlyFile来决定是否要将aof_buf的内容保存到AOF文件中,通过参数appendfysnc配置,可取三种值:always、everysec和no。
always- aof_buf内容同步写入到AOF文件,always最安全,只会丢失一次事件循环的写命令,但是性能较差
everysec 每隔一秒同步一次,默认是每秒同步一次,
no 同步事件有操作系统决定
AOF保证数据不会丢失,作为数据恢复的首选项,RDB用来做不同程度的冷备,是Redis默认持久化方式
AOF 缺点
缓存击穿是指单个key在高并发访问一下,因为缓存过期导致大量请求直接打到DB
1.加锁更新,如果缓存过期时候,针对key进行加分布式锁,只有获得锁的线程才能更新缓存,未获取锁的线程延迟读取,如果延迟读取不到直接返回空
2.不过期缓存,
缓存穿透是指查询的数据不在缓存中,每次请求都会打到DB。比如根据商品ID查询商品信息,如果有用户构造了一个不存在的商品Id去查询,此时发现缓存没有就直接查询DB
1.针对这个问题可以增加一层布隆过滤器,当请求过来时,只有通过布隆过滤器的才会查下缓存
当某一刻发生集中缓存时效导致大量请求打到DB,直接导致DB服务不可用,进而导致整个系统崩溃。
1.限流
2.针对不同的key设置不同的过期时间,避免同时过期
哨兵模式是Redis高可用(HA)的一种解决方案:由一个或多个Sentinal Instance 组成的Sentinal System可以监视任意多个主服务器和它的从服务器;在被监视的主服务器进入下线状态时,自动从slave节点中选择一个作为主服务器
集群是Redis提供了分布式数据库方案,通过分片(sharding)来进行数据共享,并提供复制和故障转移功能;一个Redis Cluster 由多个节点(node)组成。
Redis Cluster 被分为16384个slot.数据库中任意一个键都只属于16384个slot中的一个;集群中的一个节点可以处理0到16384个slot.当16384个slot都处于在线状态时集群状才是可用状态,相反任意一个slot不是在线状态,集群就处于下线状态
Redis集群中的16384个slot分配给集群中的各个节点,每个节点都会就自己负责处理的slot,哪些slot指派给了其他节点。节点在接受到一个命令请求时,首先检查这个命令要处理的键值对是否在自己负责的slot,如果不是则向客户端返回MOVE信息,并携带可以正确处理命令的节点;客户端收到MOVE信息后,根据引导数据进行重试
在接收到客户端请求后,如果发现当前源节点正在迁移slot,则客户端返回ASK
客户端通过执行subscribe命令,订阅一个或多个频道从而成为这个频道的订阅者;当其他客户端向这个频道发送消息时,订阅者会收到这条消息
127.0.0.1:6379> SUBSCRIBE "topnews"
(press Ctrl-C to quit)
1) "subscribe"
2) "topnews"
3) (integer) 1
客户端通过执行unsubscribe命令对一个或多个频道退订
127.0.0.1:6379> UNSUBSCRIBE "topnews"
1) "unsubscribe"
2) "topnews"
3) (integer) 0
客户端通过执行publish命令向指定的频道发布消息
事物就是提供一种一次性,按照顺序执行多个命令的功能;Redis通过multi, exec, watch等命令来实现事物功能。
一个事物从开始到执行结束通常可以分为三个阶段:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set "count" 1
QUEUED
127.0.0.1:6379(TX)> set "amount" 100
QUEUED
127.0.0.1:6379(TX)> DECR store
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) OK
3) (integer) -1
127.0.0.1:6379>
watch命令是一个乐观锁,它可以在exec命令执行之前,监视任意数量的数据,在在exec命令执行时,检查被监视数据是否至少有一个被修改过,如果是则服务器拒绝执行事物。
Redis提供了setbit ,getbit, bitcount,bitop 四个命令用于处理二进制位数组。bitmap非常适合用于二值统计的场景,比如布隆过滤,用户签到等场景
127.0.0.1:6379> setbit a 3 1
(integer) 0
127.0.0.1:6379> setbit a 1 1
(integer) 0
127.0.0.1:6379> setbit b 2 1
(integer) 0
127.0.0.1:6379> setbit b 1 1
(integer) 0
127.0.0.1:6379> getbit a 1
(integer) 1
127.0.0.1:6379> getbit a 2
(integer) 0
127.0.0.1:6379> getbit a 3
(integer) 1
127.0.0.1:6379> getbit b 1
(integer) 1
127.0.0.1:6379> getbit b 2
(integer) 1
127.0.0.1:6379> bitop and and-result a b
(integer) 1
127.0.0.1:6379> bitcount and-result
(integer) 1
127.0.0.1:6379> getbit and-result 1
(integer) 1
HyperLogLong是Redis2.8.9版本新增的数据类型,是一种用于“统计基数”的数据集合类型,它是基于概率的统计规则,是一种不精确的去重统计。典型的使用场景是统计百万级网页的UV,它只需要12KB内存就可以计算2^64个元素。
127.0.0.1:6379> pfadd www.cathy:uv zhansan lisi wangwu
(integer) 1
127.0.0.1:6379> pfcount www.cathy:uv
(integer) 3
本文发布于:2024-01-28 13:30:48,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064198537753.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |