redis(一)

在讲redis之前,我们先来简单的了解NoSql

NoSql:

优点: 去掉了关系数据库的"关系特性" ,易扩展 ,有非常高的读写性能 尤其大数据量下,灵活的数据模型(无需提前建立字段) 缺点:    没有统一的标准 层出不穷

四大分类:
一、键值对存储 =>redis    优势:查找速度比较快    劣势:存储数据缺少结构化
二、列存储    优势:查找速度比较快 扩展性强    劣势:功能比较局限性
三、文档数据库 =>MongoDB    优势:数据结构要求不严格    劣势:查询性能不是特别的高
四、图形数据库 =>应用于社交网络的数据库    优势:图结构的算法    劣势:不容易分布式集群方案

而redis则隶属于NoSql的第一分类,键值对存储

Redis(c语言编写、key-value形式存储):

特点:
    Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
    Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
    Redis支持数据的备份,即master-slave(读写分离,增删改由master服务器完成、查询由slave服务器完成)模式的数据备份。
    Redis还支持一些特殊数据结构,如:BitMaps(位图),  HyperLogLog(超小内存唯一值计数),GEO(地理信息定位)等。

优势:
    性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
    原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
    丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

现在让我们来看看redis的5种基本数据结构和基本操作命令。

String:

设置值set key value获取值get key重新设值,并返回旧的值getset key value
设置过期时间setex key 1000 valuekey 不存在时设置值setnx key value返回值长度strlen key
数字 增减incr key/decrkey增加5incrby key 5减5decrby key 5

Hash:

设置值hset 名称 键 值多设置 hmset 名称 键 值 键 值 ...获取hget 名称 键
多获取hmget 名称 键 键 ...删除hdel 名称 键...键值对数量hlen 名称
取所有键hkeys 名称取所有值hvals 名称是否存在hexists 名称

List:    

左插入lpush 列名 [值..] 右插入rpush 列名 [值..]查询lrange 列名 [begin,end]
左移除lpop 列名右移除rpop 列名数量llen 列名
已有列左插入lpushx 列名 [值...]已有列右插入rpushx 列名 [值...]移除lrem 列名 [count] 值
指定插入lset 列名 [index] 值插入指定值前linsert 列名 before [指定值] 值插入指定值后linsert 列名 after [指定值] 值

Set:      

设置值sadd 列名 [值...]srem 列名 [值...]查整列smembers 列名
是否存在sismember 列名 值差集sdiff 列名1 列名2并集sunion 列名1 列名2
数量scard 列名随机查srandmember 列名将差集存到新集合中sdiffstore 新列名 列名1 列名2
将交集存到新集合中sinterstore 新列名 列名1 列名2将并集存到新集合中sunionstore 新列名 列名1 列名2  

zset:可排序的set,它增加了一个顺序属性字段,用来存顺序编号(所有的指令后面都可追加withscores命令来显示元素编号)

添加zadd key  顺序编号 值删除zrem key 值返回指定元素的排名(从小到大)zrank key 值
返回指定元素的排名(从大到小)zrevrank key 值返回多个元素的排名(从小到大)zrange key 索引1 索引2 返回多个元素的排名(从大到小)zrevrange key 索引1 索引2
返回集合的数量zcard key    

Keys的通用操作:

所有键列keys * 指定开头键列keys [*]?del 键
判断存在exists 键重命名rename 旧键名 新键名设过期时间expire  键  1000
查过期时间ttl 键键的值类型type 键  

redis还支持事务及回滚的功能。
事务:开始事务:执行mukit开启事务  、命令入队:增删改命令  、执行事务: exec后,事务提交,命令会一起执行。

回滚:执行mukit命令后,set username zhangsan ,然后执行discard,那么set将不会执行。

此外,redis还存在持久化的概念。

什么是持久化:redis所有数据保存在内存中,同时在硬盘中还存储一份。
持久化方式:
快照:MySQL  dump   、Redis  RDB。
写日志:MySQL  binlog、Hbase HLog、Redis  AOF。

这里我们来了解redis的持久化。

持久化的触发方式主要有三种:save(同步)、bgsave(异步)、自动

第一种:直接执行save命令。创建了RDB文件(二进制),但是是同步的,数据较大时,会造成阻塞。如果存在老的RDB文件,将会替换
第二种:直接执行bgsave命令。异步的,由子进程来完成,完成后会返回状态给主进程。但是需要fork(创建子进程),消耗内存
第三种:自动的,有以下两种方式

1、RDB (内存快照):默认支持,不需要配置,会在硬盘创建一个RDB的二进制文件,在指定的时间间隔将数据快照写入文件,同时redis重启时会载入这个文件。
优点:
(1) 数据库只包含一个文件,通过文件备份策略,定期配置,恢复系统灾难。
(2) 压缩文件转移到其他介质上。
(3) 性能最大化,redis开始持久化时,分叉出进程,由子进程完成持久化的工作避免服务器进程执行I/O操作,启动效率高。
缺点:
(1)无法高可用:系统一定在定时持久化之前宕机,数据还没写入,数据已经丢失。
(2)通过fock分叉子进程完成工作,数据集大的时候,服务器需要停止几百毫秒甚至1秒。

 2、AOF(命令日志):需要配置开启,将以日志的形式,记录每一个增删的操作,服务器启动后,读取那个日志,执行记录的操作,构建数据库。        
优点:
(1) 同步写入,频率高,效率低,方式最安全。.
(2) 写入模式采用append模式,追加模式, 不破坏写入日志数据,在redis中追加也不会破坏文件.如果在写入一半时候就出现崩溃问题,redis下次启动之前通过 redis-check-aof这个工具来帮助数据一致性问题。
(3) 当数据过大,可启动修改重写机制,redis采用append的这种机制,将新的修改的数据不断的写到老的磁盘文件当中,同时创建新的文件保存操作,保证修改数据的更新。
(4) 日志文件格式清晰,便于重建数据。
(5) 会将一些命令进行优化:如对同一个值进行多次set,那么AOF只会保留最后一次的set。
缺点:
(1) 对于相同数据集aof文件比rdb文件大一些。
(2) 根据同步策略不同,效率比rbd低.。

同步策略:
appendfsync always 每修改一次就同步到磁盘上。不丢失数据,但IO开销较大  
appendfsync everysec 每秒会向硬盘中同步一次(默认值)。可能会丢失一秒的数据  
appendfsync no 不会主动调将AOF日志内容同步到磁盘,完全依赖于操作系统,大多数Linux操作系统,是每30秒将数据写入磁盘。

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。

redis的fork操作问题

同步操作,当fork时间过长时,会造成主线程的阻塞,redis内存越大,耗时越长(与机器类型有关,(虚拟机和物理机))
info:latest_fork_usec  查询持久化的时间,上一次执行fork的微秒数
改善fork:
              1、优先使用物理机或者高效支持fork操作的虚拟化技术。
              2、控制Redis实例最大可用内存:maxmemory
              3、合理配置Linux内存分配策略:vm.overcommit_memory
              4、降低fork频率:例如放宽AOF重写自动触发时时机,不必要的全量复制。
(vm.overcommit_memory = 1。默认是0,如果刚好要进行fork的话,fork就会阻塞。
0:表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1: 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2: 表示内核允许分配超过所有物理内存和交换空间总和的内存)

redis的过期策略都有哪些?内存淘汰机制都有哪些?

(1) 定期删除+惰性删除:所谓定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。但是问题是,定期删除可能会导致很多过期key到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。
(2) 如果redis的内存占用过多的时候,此时会进行内存淘汰,有如下一些策略:

  1. noeviction:当内存不足以容纳新写入数据时,新写入操作会报错
  2. allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key
  3. allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key.
  4. volatile-lru:在设置了过期时间的键空间中,移除最近最少使用的key
  5. volatile-random:在设置了过期时间的键空间中,随机移除某个key
  6. volatile-ttl:从已设置过期时间的数据集合中挑选即将过期的数据淘汰、

使用策略规则:
1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-rando

单线程的redis为什么这么快

(1)纯内存操作
(2)核心是基于非阻塞的IO多路复用机制
(3)单线程反而避免了多线程的频繁上下文切换问题

redis的其它特性

主从复制

        是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是实时的业务数据库,从数据库的作用和使用场合一般有几个:
      一是作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作;
      二是可在从数据库作备份、数据统计等工作,这样不影响主数据库的性能;

虚拟内存(2.6以后不再支持): 

         Redis中的虚拟内存和Linux中的虚拟内存不是一回事,但是其思想是一致的,就是把暂时不常用的数据从内存交换到磁盘中,从而可以把宝贵的内存腾出来用于其他需要访问的数据,尤其是像Redis这样的内存数据库,内存的数量无意会成为一个瓶颈。虽然我们可以把数据分割到多个服务器上,但是虚拟内存依然是一个相当有效的解决办法。当你的key很小而value很大时,使用VM的效果会比较好。因为这样节约的内存比较大,当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value。vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟,但是对数据完整性有很好的保证。Redis的数据全部放在内存带来了高速的性能,但是也带来一些不合理之处。比如一个中型网站有100万注册用户,如果这些资料要用Redis来存储,内存的容量必须能够容纳这100万用户。但是业务实际情况是100万用户只有5万活跃用户,1周来访问过1次的也只有15万用户,因此全部100万用户的数据都放在内存有不合理之处,RAM需要为冷数据买单。这跟操作系统非常相似,操作系统所有应用访问的数据都在内存,但是如果物理内存容纳不下新的数据,操作系统会智能将部分长期没有访问的数据交换到磁盘,为新的应用留出空间。现代操作系统给应用提供的并不是物理内存,而是虚拟内存(Virtual Memory)的概念。

慢查询(慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息(慢查询ID,发生时间戳,耗时,命令的详细信息)记录下来,放入一个先进先出的队列)

  • 生命周期:发送命令、命令需排队、执行命令、返回结果。
  • 慢查询发生在第三阶段、客户端超时不一定慢查询,但慢查询是客户端超时的一个因素
  • slowlog-log-slower-than:预设阀值,单位是微秒,默认值是10000,如果一条命令的执行时间超过10000微妙,那么它将被记录在慢查询日志中。0是记录所有,小于0不会记录任何命令
  • slowlog-max-len表示慢查询日志最多存储多少条。Redis使用一个列表来存储慢查询日志,slowlog-max-len就是列表的最大长度。当慢查询日志已经到达列表的最大长度时,又有慢查询日志要进入列表,则最早插入列表的日志将会被移出列表,新日志被插入列表的末尾。
  • 获取慢查询日志slowlog get [n](长度)、获取慢查询日志列表的当前长度slowlog len、慢查询日志重置slowlog reset(清空列表)

(1)slowlog-max-len的设置建议
线上环境建议调大慢查询日志的列表,记录慢查询日志时Redis会对长命令做截断操作,并不会占用大量内存。增大慢查询列表可以减缓慢查询被剔除出列表的可能性。例如线上可以设置为1000以上。
(2)slowlog-log-lower-than的设置建议
需要根据redis的并发量调整该值。由于redis采用单线程响应命令,对于高流量的场景,如果执行命令的时间在1毫秒以上,那么redis最多可支撑OPS(每秒操作次数)不到1000,因此高OPS场景的REDIS建议设置为1毫秒。
(3)慢查询只记录命令执行时间,并不包括命令排队时间和网络传输时间。因此客户端命令的执行时间要大于redis服务器实际执行命令的时间。因为命令执行排队极致,慢查询会导致命令级联阻塞,因此当客户端出现请求超时,需要检查该时间点是否有对应的慢查询,从而分析是否因为慢查询导致的命令级联阻塞
(4)慢查询日志是一个先进先出队列,慢查询较多的情况下,可能会丢失部分慢查询命令,可以定期执行slow get命令将慢查询日志持久化到其他存储中。然后制作可视化界面查询。

pipeline(流水线)
当我们客户端向redis发送一条命令时,会经过网络传输,然后到达redis执行命令返回结果。多个命令就要经过多次网络传输。
而流水线可以一次向redis发送多条命令,这样只会经过一次网络传输。

发布订阅
发布者、订阅者、频道
发布者向某个频道发布消息,订阅者订阅了这个频道,然后接受到了消息。后订阅者无法收到之前的发布消息。

以上先暂时到这,如有错误,请及时指出,本人感激不尽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值