概念
关系型数据库/sql: mysql,oracle

非关系型数据库/nosql: redis(存在内存中),mongodb(存在硬盘上)

1.redis是以key-value形式存储

2.redis支持持久化

redis用途

1.做缓存

2.存储session

3.游戏排行榜

4.对速度要求比较高的数据存储

5.做消息队列

redis 五大数据类型

1. 字符串

格式:set [key] [value]
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
string类型是Redis最基本的数据类型,一个键最大能存储512MB。

2. 列表

redis列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素列表的头部(左边)或者尾部(右边)
格式:lpush [name] [value]  # 在key对应list的尾部添加字符串元素
格式:rpush [name] [value]  # 在key对应list的头部添加字符串元素
格式:lrem [name] [index]   # key对应list中删除count个和value相同的元素
格式:llen [name]           # 返回对应list长度

3. 哈希(字典)

格式: hmset [name]  [key1] [value1] [key2] [value2]
Redis hash 是一个键值(key=>value)对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

4. 集合(set) 

格式:sadd [name] [value]
redis的Set是string类型的无序集合
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都为O(1)

5. 有序集合(zset)

格式: zadd  name score value
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。

什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失 
Redis 提供了两种持久化方式:RDB(默认) 和AOF 

RDB(Redis DataBase):

功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数 

                

AOF(Append-only file):

     	     

每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作
	aof写入保存:
	WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
	SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。

比较:

1、aof文件比rdb更新频率高,优先使用aof还原数据。
2、aof比rdb更安全也更大
3、rdb性能比aof好
4、如果两个都配了优先加载AOF

redis有哪些架构,以及特点

单机版

特点:简单
缺点:1、内存容量有限 2、处理能力有限 3、无法高可用。



主从复制 

特点:
	1、master/slave 角色
	2、master/slave 数据相同
	3、降低 master 读压力在转交从库
问题:
	1、无法保证高可用
	2、没有解决 master 写的压力



Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。 

哨兵

特点:
	1、保证高可用
	2、监控各个节点
	3、自动故障迁移
缺点:
	主从模式,切换需要时间丢数据
	没有解决 master 写的压力



					 

Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:
监控(Monitoring):   Sentinel  会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应					 用程序发送通知。
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

集群(proxy 型): 

特点:
	1、无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
	2、数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
	3、可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
	4、高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本
	5、实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色		 提升。
缺点:
	1、资源隔离性较差,容易出现相互影响的情况。
	2、数据通过异步复制,不保证数据的强一致性



从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。 

redis常用命令

Keys [pattern]   			# 查看keys是否存在,Keys * 表示查看所有key
Exists [key]  				# 查看key是否存在,有返回1,无返回0
Set [key] [value]   	 	 # 设置键值或修改已有键的值
Get [key]					# 获取单个值
Setnx [key] [value]  	 	 # 有则不变,无则设置
Setex [key] [seconds] [value]	 # 添加并设置过期时间
Expire [key] [seconds] 	 	 # 设置过期时间
TTL [key]				    # 查看过期时间
Mset [key] [value] [key] [value]...  # 设置多个键值
Getset [key] [value] 	 	 # 修改为新值并返回旧值
Mget [key] [key]...		 	 # 获取多个值
Incr [key]					# 使key的值自增1(注意:值必须为整数),若不存在则设置,并返回增后的值
incrby	[key] [increment]	 # 同Incr,可指定自增的值
Decr [key]					# 使key的值自减1(注意:值必须为整数),若不存在则设置,并返回减后的值
Decrby	[key] [decrement]	 # 同Decr,可指定自减的值
Append [key] [value]		 # 在已有的值后追加字符串,没有则设置
Strlen [key]				# 返回值的长度
move [key]	[id]			# 将 key及value移至指定库
persist [key]				# 取消过期时间
Select [id]					# 选择数据库0-15
randomkey					# 随机返回一个kay
Rename [key]				# 重命名key
Type [key]					# 返回数据类型

怎么使用redis分布式锁

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个 过期时间,防止锁忘记释放

Redis做异步队列

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

缺点:在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?

缓存穿透
	一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意	的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
	1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
	2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

缓存雪崩
	当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统	崩溃。
如何避免?
	1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和	写缓存,其他线程等待。
	2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长	期
	3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

比较redis和Memcached

  	      redis      	Memcached

数据类型 字符串,列表,字典,集合,有序集合 字符串
持久化 支持 不支持
线程线程 单线程/单进程,但速度非常快 速度较快

Redis与Mysql双写一致性方案解析

一、前言:一般用redis来缓存的流程为:

	但对于更新完数据,先更新缓存,还是先删除缓存有很大争议,因此,进行以下讨论

二、一致性方案

	1.先更新数据库,再更新缓存

	2.先删除缓存,再更新数据库

	3.先更新数据库,再删除缓存

三、先更新数据库,再更新缓存

	普遍反对,有两种原因:

1.(线程安全角度)同时请求A和请求B进行更新操作,可能会出现
	1、A更新了数据
	2、B更新了数据
	3、线程B更新了缓存
	4、线程A更新了缓存
	*此时缓存中是A的数据
2.业务场景:
	*若业务需求是更新远远大于读取,而每次都要更新缓存,则造成很大的性能浪费
	*若写入的数据不是直接写入缓存,而是要经过一些计算再写入,则也会造成性能浪费。显然,删除缓存更为合适

四、先删除缓存,再跟新数据库

	也会导致不一致的原因:

-假设线程A进行更新操作,B进行查询操作
	1、A要更新数据,先删除缓存
	2、B查询时发现没有缓存
	3、B去数据库拿到旧值,并写入缓存
	4、A将新数据写入数据库
	*此时缓存中依然是旧数据
-解决方案(延时双删策略):
	1.先删除缓存
	2.写入数据库
	3.休息1s,再删除缓存
	问题1:1s的时间怎么确定?
		根据具体的业务情况而定
	问题2:采用了mysql的读写分离架构怎么办?
		1、请求A进行写操作,删除缓存
		2、请求A将数据写入数据库了,
		3、请求B查询缓存发现,缓存没有值
		4、请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值
		5、请求B将旧值写入缓存
		数据库完成主从同步,从库变为新值上述情形,就是数据不一致的原因。解决方案依然是延时双删,在1s后再加		几百ms,等待主从同步完成
	问题3:第二次删除如果失败怎么办?
		在下面方案中具体阐述...

五、先更新数据库,再删缓存

常用的是这种,虽然理论上还是有点问题:

-假设线程A进行查询,线程B进行更新
	1.缓存刚好失效
	2.请求A进行查询,查到一个旧值
	3.请求B进行更新数据库
	4.请求B进行删除缓存
	5.请求A将取到的旧值添加到缓存,造成脏数据
-讨论
	这种情况发生的情况几乎不存在,因为查询的速度要远大于写入的速度,因此在2进行后不可能会等3,4执行完了,才执行5。那如果删除缓存失败了怎么办?

为了解决删除缓存失败的问题,可用下面两种方案:

一、如图



二、如图



备注说明:上述的订阅binlog程序在mysql中有现成的中间件叫canal,可以完成订阅binlog日志的功能。另外,重试机制,可采用的是消息队列的方式。如果对一致性要求不是很高,直接在程序中另起一个线程,每隔一段时间去重试即可,这些大家可以灵活自由发挥,只是提供一个思路。 

python操作redis

1.简单使用

import redis
conn = redis.Redis(host='localhost',port=6379)  # 获取reis链接
conn.set('age','18')  # 存入数据(reids里存的都是byte格式数据)
name = conn.get('name')  # 获取数据
print(name)

2. redis连接池

	1.新建一个模块conn_pool.py

import redis
POOL=redis.ConnectionPool(host='localhost',port=6379,max_connections=1000)

	2.使用连接池

from conn_poll import POOL
conn=redis.Redis(connection_pool=POOL)
print(conn.get('name'))

3.需要重点掌握的字符串操作

	get  set  mget  mset  incr  decr  append
 posted on 2019-10-17 12:39  ._东汕再  阅读(115)  评论(0编辑  收藏  举报