Redis深度历险 读书笔记

Redis基础数据结构

String(字符串)、 list(列表)、 hash(字典)、set(集合)、zset(有序集合)

String

Redis的字符串是动态字符串,可以进行修改,内部结构实现类似于ArrayList,采用预分配冗余空间 的方式减少内存的频繁分配。字符串的最大长度为512MB

  • 添加一个字符串 set name value
  • 获取一个字符串 get name
  • 判断是否存在 exists name
  • 删除 del name
  • 添加多个字符串 mset name1 value1 name2 value2
  • 获取多个字符串 mget name1 name2
  • 设置过期时间(秒) expire name 5
  • 自增 incr name 10 自增存在范围, 范围在signed long的最大值最小值之间,超出会报错。

字符串由多个字节组成,每个字节由8个bit组成。

List

Redis的list类似于LinkedList,由链表组成。插入和删除很快,时间复杂度为O(1)。定位较慢,时间复杂度为O(n)。
通常用来做异步队列使用

  • 先进先出(队列)
    • push操作 rpush listname value1 value2 value3
    • pop操作 lpop listname
  • 先进后出(栈)
    • push操作 rpush listname value1 value2 value3
    • pop操作 rpop listname
  • 通过下标获取 lindex listname 1
  • 获取范围内元素 lrange listname 0 1
  • 截取范围内元素 ltrim listname 0 1
Hash

Redis的Hash类似于HashMap,是一个无序字典,内部存储键值对。

  • 添加 hset hash key value
  • 添加多个 hmset hash key1 value1 key2 value2
  • 获取单个 hget hash key
  • 获取全部 hgetall hash
  • 长度 hlen hash
Set

Redis的set类似于Java的HashSet,具有去重功能。

  • 添加 sadd set value1
  • 获取一个 spop set
  • 获取全部 smembers set
  • 判断是否存在 sismember set value1
  • 获取长度 scard set
zset

Redis的zset类似于SortedSet和HashSet的结合体,一方面是一个set,另外给每一个value赋予一个score,代表排序权重。

  • 添加 zadd zset 9.0 value1
  • 按照score列出 zrange zset 0 -1
  • 倒序列出 zrevrange zset 0 -1
  • 获取value的score zscore zset value
  • 排名 zrange zset value1
  • 根据分值区间遍历 zrangebyscore zset 0 9.0
  • 删除 zrem zset value1

zset内部排序通过“跳跃列表”实现。

list,set,hash,zset 四种数据结构是容器型数据结构。

  • create if not exists: 如果不存在就会新建一个进行操作。
  • drop if no elements: 容器中没有元素就会删除。

过期时间:Redis所有的数据结构都可以设置过期时间,时间到了会自动删除。过期以对象为单位,会删除整个数据结构,而不是删除其中的元素。如果一个字符串已经设置了过期时间,再调用set,过期时间会消失。

Redis应用

分布式锁

分布式应用在进行逻辑处理时,存在竞争,会出现并发问题。需要使用分布式锁来限制程序。

使用setnx(set if not exists)指令,只允许被一个客户端使用,使用后再调用del指令移除。当程序运行中出现异常或导致del指令不会执行,陷入死锁。因此可以加入一个过期时间,使用expire指令。

如果服务器在setnx和expire中间崩溃,expire不会执行,也会造成死锁。因此需要其他方法保证其原子性

在Redis 2.8版本加入了set指令,使setnx和expire指令可以一起执行。set key value ex 5 nx

超时问题: 如果某一段程序运行过慢,在expire期间并没有执行完,第二个线程就会提前获取锁。因此,Redis尽量不要用于较长时间的任务。

可重入性:如果一个锁支持同一个线程多次加锁,那么这个锁就是可重入的。Redis分布式锁如果想支持可重入,需要对客户端的set方法进行包装,使用线程安全类Threadlocal变量存储当前持有锁的计数。

集群问题: 在集群中,当主节点挂掉时,从节点会取而代之。但是客户端对此并没有感知。比如客户端先从主节点获取到了锁,然后主节点挂掉,从节点取代。而新的主节点内部没有这个锁,当另一个客户端请求加锁,立即就批准了。这样会导致同一个锁会被多个客户端获取。

Redlock算法: 该算法会向过半节点发送set(key, value, nx=true, ex=xxx)指令, 只要过半节点set成功,就认为加锁成功。释放锁会向所有的节点发送del指令。Redlock算法会向多个节点进行读写,意味性能会下降。如果很在乎高可用性,可以考虑使用。代价就是丧失了性能。

延时队列

Redis可用list实现一个异步消息队列,使用rpush和lpush入队,lpop和rpop出队。但是没有ack确认,不能保证消息的可靠性。
如果队列空了,pop操作会陷入死循环,会造成提高客户端CPU消耗。可以使用blpop或brpop指令,字符b代表的是blocking,也就是 阻塞读。阻塞读在队列没有数据的时候立即进入休眠状态,数据到来继续操作。

当线程一直阻塞,Redis连接会变成闲置连接。闲置过久会与服务器断开连接,这个时候blpop或brpop会抛出异常。编写代码需要捕获异常进行处理。

延时队列的实现: 可以通过zset实现,消息为value,到期处理时间为score,然后使用多个线程轮询zset获取到期任务进行处理。多个线程保障可用性,也会带来并发问题。

位图

位图不是特殊的数据结构,内容就是普通的字符串,也就是byte数组。可以使用普通的get\set方法获取和设置。也可以使用getbit\setbit将byte数组看成“位数组”处理。

  • Redis的位数组是自动填充的,如果某个偏移量超出了现有的内容范围,将会用0填充。
  • 设置字符串时只需要设置值为的位。
  • 可以进行按单个位或者整体s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值