Redis基础原理总结

Redis是一个基于内存的、单进程单线程模型的高性能kv数据库,目前使用量可以说吊打所有缓存中间件,尤其是在分布式系统中,redis可以满足很多场景需求,比如最常用的数据缓存,还有计数器、分布式session、分布式锁、消息队列等,小编就用redis的sortedset实现过一个排队系统,非常好用。

核心数据结构

对于redis的数据结构,相信用过的小伙伴都知道:

string

list

set

sorted set

hash

但在比较新的redis版本中还提供了一些高级的数据结构,比如HyperLogLog,但是小编也没用过,后面研究研究在分享给各位(此处不得不感慨每种框架、中间件都在快速发展,一点都不考虑程序员们的头发)。

下面列举几个小编接触过的、使用比较频繁的场景(此处很希望有同学能在评论里补充)。

用哈希表缓存购物车。(这里说的购物车指的是登录状态下的购物车,未登录状态下的购物车一般会塞到cookie里,登录后再合并)。

hset cart:userid goodsid nums #加入商品到购物车hincrby cart:userid goodsid   #调整购物车中商品的数量hlen cart:userid #获取购物车中所有商品的数量hdel cart:userid goodsid #从购物车中删除某个商品hgetall cart:userid #获取购物车中的商品列表

注:在使用hash结构时,应该尽量避免field数量过多,为什么呢?因为redis是单线程模型,field数量太多,会导致某些操作非常耗时这会使redis服务出现停顿,高并发场景下非常危险!!!!

利用set实现抽奖

sadd promotionKey userid #参与抽奖smembers promotionKey #查看参与抽奖的人srandmember promotionKey count   #随机抽count个用户,但不删除

//Removes and returns one or more random elements //from the set value store at keyspop promotionKey count #随机抽count个用户,并将其从集合中删除,这对于需要多次抽奖的场景非常有用

利用有序集合实现排行榜(这个应该是很常用的,尤其是在一些后管系统中)

zincrby hotkey_20191118 1 key01 #key01 + 1,一般对应一次点击或数据流中的一条数据zrevrange hotkey_20191118 0 10 with score # 查询排行榜前10

#对多天的数据进行合并,这个也挺常用的#思路就是 将多天数据合并和存储到一个单独的key中,在revrangezunionstore hotkey_201916_18 hotkey_20191116 hotkey_20191117 hotkey_20191118zrevrange hotkey_201916_18 0 10 withscore

分布式锁

#加锁set lockkey 0 ex 5 nx #解锁del lockkey

用nx实现锁竞争,用ex增加超时时间,避免死锁,但是这样实现的分布式锁很简陋,不支持阻塞、超时获取锁、不支持可重入等,只能用在简单场景中,例如小编曾经用这样的redis 分布式锁实现了在多个定时任务之间互斥执行的逻辑,主要因为不涉及到重入等高级特性,获取锁成功就执行,失败就returen掉。

如果需要高级特性的话,小编建议使用一个叫Redission的工具,这玩意很强大,可以说就是个分布式的java.util.Lock,附上github地址(https://github.com/redisson/redisson),感兴趣的同学可以去看看。

持久化策略

Redis基于内存,在掉电和服务宕机的情况下很容易造成数据丢失,为此Redis提供了持久化机制来保证数据的可靠性。

目前在最新版的Redis中支持三种持久化策略:

RDB 

AOF

RDB + AOF混合模式

RDB模式是通过数据快照的方式进行数据持久化的,可以通过修改配置文件中的save参数来指定具体的RDB持久化策略。

# 900秒内有一次修改save 900 1#300秒内有10次修改save 300 10#60秒内有1000次修改save 60 1000

当进行数据持久化时,Redis主线程fork出一个子进程将内存中的数据以二进制的方式持久化到磁盘上。使用RDB持久化策略的好处在于他不影响主线程对外服,另外用RDB文件进行数据重建的速度也比较快,但是凡事都有两面性,RDB模式会造成部分数据丢失,因为不是对数据实时持久化,另外一点是如果内存中的数据量比较大的话,数据持久化线程也会长时间抢占系统资源,造成主线程服务性能下降,但一般情况下,这个问题都不是问题,因为我们在使用Redis的时候都是集群部署,例如Sentinel和Cluster两种进群模式,很容易实现读写分离和数据分片,都能比较好的缓解这个问题。

Redis基础原理总结

扫一扫手机访问