学习redis知识的过程
1. 概念
redis是一个key-value存储系统。它支持存储的value类型多,包括string(字符串),list(链表),set(集合),zset(有序集合) 和 hash(哈希)。他不是一个关系型数据库,Redis是单线程的,基于事件驱动的
2. 特点
1. redis 以内存作为数据存储,读写的效率很高。
2. redis支持主从模式,配置redis集群,便于支撑更大型的项目。
3. redis的所有操作都是原子性的,要么成功执行,要么失败完全不执行。单个操作时原子性的。多个操作也是支持事务。
4. redis运行再内存中,但是可以持久化到磁盘,所以在对不同数据进行高速读写的时候需要权衡内存,数据量不能大于硬件内存。再内存中的一个优点是,相比在磁盘上的复杂的数据结构,内存中操作起来就比较简单。
3. redis应用场景
众多语言都支持redis,因为redis交换数据比较快,所以在服务其中常用来存储一些需要频繁调取的书记,这样可以大大节省系统直接读取磁盘来获得数据的i/o开销,可以极大提升速度。
拿大型网站来举个例子,比如某网站首页一天有100万人访问,其中有一个板块为推荐新闻。要是直接从数据库查询,那么一天就要多消耗100万次数据库请求。上面已经说过,Redis支持丰富的数据类型,所以这完全可以用Redis来完成,将这种热点数据存到Redis(内存)中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销
4. redis的数据类型
切换数据库
select 数据库编号
set key value 设置key对应的string类型的value
setnx key value 同上,如果key已经存在,返回0.nx 是 not exist 的意思
get key 获取 key 对应的string 值,如果key不存在返回nil
getset key value 原子的设置 key的值,并返回key的旧值。如果 key 不存在返回 nil
mget key1,key2 一次获取多个 key的值,如果对应key不存在,则对应返回nil
2. list 类型实质是每一个元素都是string类型的双向链表,所以push和pop命令的算法时间复杂度都是O(1),另外list还会记录链表的长度,所以len操作也是O(1)。
lpush key string 在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list
rpush key string 同上,在尾部添加
lpop key 从list 的头部删除元素,并返回元素。如果key 对应list 不存在或者是空返回nil,如果key 对应的不是list返回错误
5. 什么是Redis缓存穿透,缓存雪崩?
缓存传透是查询一个一定不存在的数据时,由于缓存中不存在,每次请求总时穿过缓存,从数据库中查询,造成缓存穿透。
缓存雪崩时指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬间压力过重雪崩。
解决办法:
缓存穿透
最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
如果一个查询返回的数据为空(不管时数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
缓存雪崩
加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超过是i,这是个治标不治本的方法。
注意:加锁排队的解决方式分布式环境的并发问题,有可能还要解决分布式锁的问题:线程还会被阻塞,用户体验很差,因此,在真正的高并发场景下很少使用。
关于缓存崩溃的解决方法,这里提出了三种方案:使用锁或队列,设置过期标志更新缓存,为key设置不同的缓存失效时间,还有一种被称为“二级缓存”的解决方法。
django 使用redis需要注意的地方
redis 缓存配置,在settings.py中
CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/9', 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', } } }
在views.py中
from django_redis import get_redis_connection conn = get_redis_connection('default') value = conn.hget()
然后就可以使用redis的 一些方法