NoSQL,Not Only SQL 泛指非关系型数据库(关系型数据库是指使用标准SQL语言进行操作),以键值对的形式储存,与关系型数据库是相辅相成的。
具有以下优点:
易扩展:数据与数据之间没有关系
高性能:NoSQL数据库都具有非常高的读写性能,尤其是在大数据下同样表现优秀,得益于他的无关性和结构简单
灵活的数据模型:无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。
Redis(Remote Dictionary Server),即远程字典服务,是一个开源的,用C语言编写的,支持网络交互的,以key-value数据结构存储,支持多种语言,可以作为数据库、缓存和消息的中间件。
主要用来做数据的缓存(让数据离程序更近),Redis运行在内存中,数据也保存在内存中。
Redis及其他key-value缓存产品的特点:
关系型数据库:
采用关系模型来组织数据,关系模型就是二维表格的模型。一张二维表的表名就是关系,二维表的一行就是一条记录,二维表中的一列就是一个字段。
优点:
容易理解,使用方便,通用的sql语言,易于维护,丰富的完整性(实体完整性,参照完整性和用户定义的完整性)大大降低了数据冗余和数据不一致的概率缺点
缺点:
非关系型数据库:
分布式,一般不保证ACID原则的数据存储系统。键值对存储,结构不固定。
优点:结构简单易扩展,高性能,灵活的数据类型
缺点:适合放一些简单的数据,不适合放时间太久太多的数据
键都是String类型
String(字符串),List(列表), Hash(哈希),set(集合), zset(有序集合)
简单动态字符串(string),双向链表(list),压缩列表(list hash zset),哈希表(hash set),跳表(zset),整数数组(set)
底层是hash结构,可以通过key计算出位置,将key-value都存在此位置,也可以存其他类型;
hash冲突问题:提供两块内存空间,将原来的映射渐进式的复制到扩容后的hash表中,然后释放之前的空间
是二进制安全的可以包含任何数据,比如jpg图片或序列化对象,最大能存储512MB
单值缓存:比如 phone:13392039203
set key value
get key
del key
对象缓存(不对对象中数据操作时可以使用):
set user:1 value(json 格式数据)
计数器:
set news_views:1 0 设置文章访问量
incr news_views:1 文章访问量+1
decr news_views:1 文章访问量-1
get news_views:1 获得值
Web 集群 session 共享
session + redis 实现 session 共享
hash特别适合用于存储对象(对对象中数据发生修改的情况),存的是字符串和字符串值之间的映射,比如要存储用户购物车等信息。
hset key field value 存储一个哈希表的键值
hmset key field value [field value……] 存储多个键值对
hget key field 获取
hmget key field [field……] 获取多个
hdel key field [field……] 删除
hlen key 返回哈希表key中的field的数量
hgetall 返回哈希表key中所有的键值
hincrby key field 增加值(负数时,减少)
电商购物车
1)以用户 id 为 key
2)商品 id 为 field
3)商品数量为 value
购物车操作
1)添加商品→hset cart:1001 10088 1
2)增加数量→hincrby cart:1001 10088 1
3)商品总数→hlen cart:1001
4)删除商品→hdel cart:1001 10088
5)获取购物车所有商品→hgetall cart:1001
Redis 列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)。可以实现队列或者栈
lpush key value[value……]将一个或多个值插到key列表的表头(最左边)rpush key value[value……]将一个或多个值插到key列表的表尾(最右边)lpop key 移除并返回 key 列表的头元素
rpop key 移除并返回 key 列表的尾元素
lrange key start stop 返回列表key中指定区间内的元素,区间以偏移量start
和 stop(从1开始)
使用场景:可以用来存储接收到的消息数据.
Redis 的 Set 是无序集合。
sadd key member[member…] 往集合 key 中存入元素,元素存在则忽略,
若 key 不存在则新建
srem key member[member…] 从集合 key 中删除元素
smembers key 获取集合 key 中所有元素
scard key 获取集合 key 的元素个
redis zset 也是不允许重复的成员,但是是有序的。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为
集合中的成员进行从小到大的排序。
zset 的成员是唯一的,但分数(score)却可以重复。
zadd key score member[[score member]…] 往有序集合 key 中加入带分值元
素
zrem key member[member…] 从有序集合 key 中删除元素
zscore key member 返回有序集合 key 中元素 member 的分值
zincrby key increment member 为有序集合 key 中元素 member 的分值
加上 increment
zcard key 返回有序集合 key 中元素个数
zrange key start stop[withscores] 正序获取有序集合 keyastart 下标到 stop
下标的元素(从0开始)
使用场景:记录微信朋友圈记录点赞用户
有时候我们并不希望Redis的key一直存在,例如缓存,验证码等数据,Redis提供了一些命令,能够让我们对key设置过期时间,并且让key过期后自动删除。
EX表示以秒为单位;PX表示以毫秒为单位;不区分大小写
ttl 键 查看剩余多少秒
pttl 键 查看剩余多少毫秒
举例:可以直接 set name jim ex 30
也可设置值后设置有效时间:expire name 30(秒)
pexpire name 30 000(毫秒)
Redis6.x之前是真正意义上的单线程,处理客户端的连接和执行操作命令都是由一个线程完成的;Redis6.x引入了多线程,处理客户端的请求由专门线程处理,执行操作命令仍然是单线程。
Redis数据是存储在内存中的,内存中数据是临时保存,Redis是支持将数据持久化到硬盘的。Redis为我们提供了两种持久化的机制,分别是RDB(Redis DataBase)和AOF(Append Only File);这两种方式都可以在redis.conf中进行配置,默认使用的是RDB方式
RDB方式:直接将内存中的数据快照(k-v)存储起来;触发持久化的机制:
备份就会自动生成一个dump.rdb文件
AOF方式:以日志的形式,将写命令存储到文件中,还原时,将命令逐个执行还原数据
默认不开启: appendonly no 改为yes开启
同步机制:appendsync always 每set一次记录一次;appendsync everysec 每一秒记录一次(可能丢失一秒数据)
重启redis生效
Redis在执行单挑命令时,是原子性的(单线程一次只能有一个线程执行命令)
有时候,一次操作需要执行多条命令,可以通过redis事务来实现多条命令的整体执行
主从是指主机和从机,是集群架构;如果只用一个redis,万一其意外宕机,所有请求都会到达MySQL,导致MySQL宕机;这时可以搭建多台redis服务器,万一其中有故障出现,其余的redis服务还可以正常使用
主机负责写数据,将数据同步到从机,一般的读数据从从机查询,实现了读写的分离,即写命令由主机执行,读命令由从机执行
作用:
哨兵(sentinel)有一个单独的线程,对集群中的多台服务器进行监听,给每个服务器发请求,如果没有响应,表名出现了故障,当主机意外宕机时,会从从机中选取一个当做主机,当原主机恢复后又作为主机继续使用;哨兵也可集群,除了监控各个redis服务外,哨兵之间也可互相监控
为key设置过期时间当时间到了之后有以下三种策略可选:
查询数据流程:查询数据是否在redis中,在就返回,不在去数据库查询,然后将数据添加至redis并返回
缓存穿透:查询的数据在数据库中没有,在Redis中也没有,每次还是会去访问数据库
解决办法:
缓存击穿:数据库中有数据,只是某个热点key在某个时间点上过期了,此时有大量请求到达,查询缓存没有,一起都向数据库发请求,导致数据库崩溃
解决办法:
缓存雪崩:大量的热点key过期或redis服务器故障,导致大量请求到达数据库,导致数据库崩溃
解决办法:
雪崩是大面积的key缓存失效,穿透是redis里面不存在这个缓存key,击穿是redis某个热点key突然失效,最终的受害者都是数据库
对于“redis宕机,请求全部走数据库”这种情况我们可以有以下的思路: