Redis学习系列,基础数据结构,位图,分布式锁

一、redis基础数据结构
redis中所有数据结构都是以唯一key作为名称,并通过key获取value数据,不同的是value的数据结构不同
五种数据结构:
string(字符串):使用非常广泛,常见的是存储用户信息。
字符串是动态字符串,是可以修改的字符串,在内部使用预先分配冗余空间减少内存频繁分配
字符串长度小于1MB时扩容是加倍,大于1MB时是扩容一次加1MB。最大长度是512MB
list(列表):是链表,插入和删除时间复杂度是O(1),查找为O(n)。每个元素都使用双向指针,前后都可以便利
常用来做异步队列使用,可以实现队列(确保顺序访问)和栈
底层结构:称为快速链表(quicklist),在列表元素较少时会使用连续内存存储,被称为ziplist(压缩列表)
数据多时会分配多个ziplist,然后使用双向指针串起来,称为quicklist。
优点:快速链表既满足快速插入删除性能,也不会有太大的数据冗余
hash(字典):和数据结构中的hash是一样的即“数组+链表”,redis中hash的值只能是字符串,rehash的方式为渐进式策略
渐进式rehash:在rehash时会保留新旧两个hash结构,查询时会同时查询两个hash结构,然后在后面的定时
任务与hash操作中,循序渐进的将旧hash中的内容迁移到新的里面,直到搬迁完成。
set(集合):内部的键值对是无序的、唯一的(有去重功能)
zset(有序集合):既保证value的唯一性(set),又会给每一个value赋予一个score代表value的排序权重
内部实现:跳跃列表,zset需要支持随机插入和删除,在新插入元素时需要保证有序,跳跃列表类似层级结构
每一个元素可能存与多个层次,使得可以快速的不同层次之间跳跃

容器型数据结构的通用规则(list,set,hash,zset):
a、如果容器不存在就创建一个,再进行操作
b、如果容器里元素没有了,那么立即删除容器,释放内存
过期时间:
redis中可以设置过期时间:过期时间以对象为单位,而不是单个key的过期时间

二、分布式锁
redis分布式锁的使用:
set(抢占锁)----》setnx(设置锁)-----》expire
一般情况下客户端先抢占锁,使用完成后再对锁进行释放(del指令),为了解决由于异常使得del没有被执行,
因此为锁加上过期时间,时间到了就自动执行,但是如果因为setnx和expire之间的故障使得expire不能执行也会造成死锁
setnx和expire应该是前者执行后者必须执行,类似于事务
redis中的解决给set的参数进行了扩展命令:
set lock:codehole true ex 5 nx
del lock:codehole
将setnx和expire组合在一起的原子指令
可重入性:一个锁可以支持同一个线程多次加锁
三、延时队列
redis的消息队列实现简单,但是没有ack保证,如果是对于消息的可靠性有极高要求的,它则不适合使用
异步消息队列:
redis的list常用来做异步消息队列,使用rpush和lpush操作入队,lpop和rpop操作出队
支持多个生产者和多个消费者并发进出消息,每个消费者都会拿到不同的列表元素
队列空时的处理:如果队列空时pop会陷入死循环,这样会消耗客户端和服务端的资源,
一般会使用sleep来让线程等待
阻塞读:睡眠会导致延时加大,使用blpop/brpop阻塞读,让线程进入休眠,当有数据时立即唤醒
阻塞时redis客户端的连接就成了闲置连接,时间过程服务器就会断开连接,blpop和brpop会抛出异常,客户端需要捕获,并重试
锁冲突处理:
一般的三种方式:
直接抛出异常,通知用户稍后重试(影响用户体验)
sleep一会,然后重试(不适合频繁的操作)
将请求转移至延时队列,过一会再试(适合异步消息处理)

四、位图
实际应用中记录用户的签到记录,如果使用普通的key/value,会使得存储空间增加
redis中提供了位图,每一条记录占用一位,即byte数组
1、基本用法:
redis的位数组是自动扩展的,再使用位图存储字符串时,需要将字符串转为ascii,然后进行相应的设置
值设置为1的位,再设置时可以一位一位进行设置,也可以进行一次填充
如果获取的元素是不可打印的将显示位十六进制
2、统计和查找
bitcount统计指令:用来统计指定范围内1的个数
bitpos查找指令:用来查找指定范围出现的第一个0或1
指定范围[start,end]start和end是字节索引,即指定范围必须是8的倍数
3、魔术指令bitfield
bitset和bitget只可以对单个位操作
bitfield一次可以进行多位操作(最多64个连续位),有三个子指令set,get,incrby可以对指定片段进行读写操作
incrby是对指定范围的位进行自增操作,如果溢出redis默认折返,无符号8位255会变成0,有符号-127会变成-128
用户可以使用overflow设置溢出策略,默认是折返,还可以选择报错不执行,饱和截断超过范围就停留再最大或最小值

猜你喜欢

转载自blog.csdn.net/alvin_666/article/details/89068536