redis入门笔记

1.redis默认有16个数据库 用的是第0个数据库
  可以用select进行切换数据库
  select 3     切换到第三个数据库
  dbsize       查看数据库大小
  keys *       查看所有的key
  flushdb      清空当前数据库
  flushall    清空所有数据库
  move key db  移动当前数据到其他数据库
  set name xx  存入新的键值对
  del key      移除key
  EXPIRE key seconds   设置key过期时间,单位是秒
  ttl key      查看当前key的剩余时间
  type key     查看当前key的一个类型

2.redis是单线程的 版本6是多线程了
  redis是基于内存操作的,CPU不是redis性能瓶颈,redis的瓶颈
  是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用了
  单线程 
3.redis是C语言写的,官方提供的数据为10w+的QPS,完全不比Memecache差

4.为什么单线程还这么快?
  ①误区1:高性能的服务器一定是多线程的? 
    误区2:多线程(CPU上下文会切换 也会耗费资源)一定比单线程效率好
           要对CPU>内存>硬盘的速度有所了解
  核心:redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的
       对于内存系统来说,如果没有上下文切换效率就是最高的。多次读写都是在一个CPU上的
       在内存情况下,这个就是最佳的方案 

5.redis可以用作数据库、缓存、消息中间件MQ

6.String类型
   EXISTS key 判断某一个key是否存在
   APPEND key "xxx"  追加字符串 如果key不存在则新建一个key 
   STRLEN key  获取字符串的长度
   incr key    自增1
   decr key    自减1
   INCRBY key  10  设置步长,指定增量10
   DECRBY key  10
   GETRANGE key1 0  3 截取0-3的字符串
   GETRANGE key1 0 -1 获取全部key1的值
   SETRANGE key1 6 czy1  将key1的值的第6为开始改为czy1
   
   setex(set with expire) 设置过期时间
   setex key1 30 “hello” key1为hello 30秒后过期   

   setnx (set if not exist)不存在设置(在分布式锁中会常常使用)
   setex key1 “hello” 如果key1不存在则设置为hello 存在则失败   

   mset k1 v1 k2 v2 k3 v3 同时设置多个值
   mget k1 k2 k3          同时获取多个值
   mesetnx 是个原子操作 要么一起成功,要么一起失败

   set user:1 {name:lisi,age:21} 设置一个对象
   get user:1  "{name:lisi,age:21}"
  
   getset db redis 先获取db的值在set
   
   String类似的使用场景:value除了是我们的字符串还可以是我们的数字
    ·计数器
    ·统计多单位数量
    ·粉丝数
    ·对象缓存存储


7.List类型
  在redis里面可以把List玩成栈、队列、阻塞队列
  所有list命令都是以l开头的

   LPUSH list one 将一个或多个值,插入到列表的头部
   RPUSH list four  将一个或多个值,插入到列表的尾部
   
   LPOP list 1  移除列表的第一个元素
   RPOP list 1  移除列表的最后一个元素
   LINDEX list 0 根据索引获取值 获取列表的第一个值
   LLEN list     获取列表长度
   LREM list 1 three   移除list中指定个数的value
   ltrim mylist 1 2    通过下表截取指定的长度 list已经被改变了 只剩下截取的元素
   rpoplpush mylist myotherlist  去除最后一个值插到myotherlist头部
   lset list 0 item  将0号索引处的值改为item 但是值必须存在 不然报错 
   LINSERT list before world niubi  在world前面插入niubi 后面用after


8.Set类型
  没有顺序 值不能重复
  sadd myset love 添加元素
  SISMEMBER myset world 判断world值是不是在set集合中
  SMEMBERS myset 列出所有成员
  scard myset  获取元素个数
  srem myset hello   移除hello
  SRANDMEMBER myset 2 随机获取两个元素 默认取一个
  spop myset  随机删除一个元素
  smove myset myset2 love  移动指定的值到另一个集合
    
   数字集合类:
     -差集 SDIFF key1 key2  以key1做参照物 key1中有 key2中没有的
     -交集 SINTER key1 key2
     -并集 SUNION key1 key2

  


9.Hash
  Map集合,key-<key,value> 
  hset myhash field1 kuangshen set一个键值对
  hget myhash field1  获取值
  hmset myhash field1 hello field2 world  set多个
  hmget myhash field1 field2   获取多个
  hgetall myhash 得到所有值
  hdel myhash field1 删除键值对
  HLEN myhash 有几个键值对
  HEXISTS hash 1 判断hash中的key是否存在
  HKEYS hash 获取所有key
  HVALS hash 获取所有的值
  HINCRBY hash 4 5  给key为4的值加5 减法也行
  hsetnx myhash field value 如果不存在则可以设置 存在不能
 

10.Zset 有序集合
  在set的基础上,增加了一个值,set k1 va | zset k1 score1 v1
   zadd salary 2500 zhangsan
   zadd salary 1500 lisi
   zadd salary 100 lyx

   ZRANGEBYSCORE salary -inf +inf 负无穷 正无穷 从小到大排序
    1) "lyx"
    2) "lisi"
    3) "zhangsan"

   ZRANGEBYSCORE salary -inf +inf withscores
    1) "lyx"
    2) "100"
    3) "lisi"
    4) "1500"
    5) "zhangsan"
    6) "2500"

   ZRANGEBYSCORE salary -inf 1500 withscores
    1) "lyx"
    2) "100"
    3) "lisi"
    4) "1500"

   zrem salary lyx  移除指定元素
   zcard salary     元素数量
   ZRANGE salary 0 -1    从小到大输出
   ZREVRANGE salary 0 -1  从大到小输出
   zcount myset a b  a和b之间有几个值 包括a和b
    

11.geospatial 地理位置 底层原理是Zset
   朋友的定位、附近的人、打车距离计算
   只有6个命令
   geoadd china:city 120.16 30.24 hangzhou
   //key经度纬度城市名 但是南极北极无法添加。我们一般会下载数据,通过java程序一次导入
     有效经度 -180-180  有效纬度-85.05-85.05
    
   geopos china:city beijing
   //获取指定城市的经度和维度
   
    geodist china:city beijing shanghai km
    //获取两地直线距离 默认单位是m 可以改单位km mi(英里) ft(英尺)

    georadius china:city 110 30 1000 km withdist
    //以110 30 经纬为中心方圆1000km为半径的用户  加上withdist可以得到直线距离
      加上withcoord可以得到经纬    加上count 200 查出200个
  
    GEORADIUSBYMEMBER china:city beijing 1000 km
    //以城市为中心
  
    geohash china:city beijing
    //将经纬度转换成字符串 两个城市字符串越接近 距离越近

    zset的命令都适用于geo

12.hyperloglog
   基数(不重复的元素)
   基数统计算法 
   业务:网页的UV(一个人访问一个网站多次,还是算作一个人)
   传统方式:set保存用户的id,然后就可以统计set中的元素数量作为标准判断
   这种方式如果保存大量的用户id,就会比较麻烦。我们的目的是为了计数,而不是保存用户id;
 
   hyperloglog优点:占用的内存是固定的,2^64不同的元素的技术,只需要12kb的内存,
       如果从内存角度来比较,这个就是首选  0.81%错误率 可以忽略不计

    pfadd mykey a b c d e f g h i j 添加元素
    pfcount mykey  多少个元素
    pfadd mykey i j m n  i和j不会被添加进去
    pfmerge mykey3 mykey1 mykey2 合并后两个得到mykey3

13.bitmaps 位图 操作二进制位进行记录 只有0和1两个状态 位存储
   两个状态的都可以使用bitmaps

    setbit sign 0 1   周一打卡
    setbit sign 1 0   周二没打卡
    getbit sign 3     查看周四是0还是1
    bitcount sign    统计有几天是1  后面还可以跟开始和结束日期


14.事务
   redis单挑命令是保证原子性的,但是事务不保证原子性
   redis事务本质:一组命令的集合 一个事务的所有命令都会被序列化,在十五
      执行过程中,会按照顺序执行
   redis没有隔离级别的概念 所有命令在事务中并没有直接被执行 只有发起执行命令exec的时候才会执行
   特质:一次性、顺序性、排他性 执行一系列的命令      

   redis:
     ·开启事务( multi )
     ·命令入队(一些命令)
     ·执行事务(exec)
     ·取消事务(discard)事务队列中的命令都不会被执行

   编译型异常(代码有问题,命令有错),事务中的所有命令都不会被执行
   运行时异常(1/0),如果事务队列中存在语法性错误,其他命令可以正常执行,错误命令抛出异常
   锁:redis可以实现乐观锁 
  

15.监控
   悲观锁:很悲观,认为什么时候都会出现问题,无论做什么都会加锁
   乐观锁:·很乐观,认为什么时候都不会出现问题,所以不会上锁,更新数据的时候
            去判断一下,在此期间是否有人修改过数据
           ·获取version  
           ·更新的时候比较version
-----------------------------------------------------------
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money //监视redis
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20

事务正常结束,数据在期间没有发生变动,这个时候正常执行成功
-----------------------------------------------------------------
测试多线程修改值,使用watch可以当作redis的乐观锁操作
执行exec之前另外一个线程修改了数据,则exec失败

watch使用完毕后(事务执行失败) 需要unwatch 然后重新watch拿到最新的值


16.在springboot2.x之后,原来的jedis被替换为了lettuce
   jedis:采用的直连,如果有多个线程操作的话,是不安全的,想要解决就需要jedispool连接池  BIO模式
   lettuc:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况,可以减少线程数量 NIO模式

17.redis.conf详解
  单位
    配置文件unit单位对大小写不敏感
  包含
    可以把别的地址的配置文件导入进来
  网络
     bind 127.0.0.1 绑定的ip
     protected-mode yes  保护模式 默认开启
     port 6739  端口设置
  通用
     daemonize yes 默认是no 开启了yes  以守护进程的方式运行
     pidfile /var/run/redis_6739.pid 如果以后太的方式运行,我们就需要指定一个pid文件
     loglevel notice 日志
     logfile “” 日志生成的文件名
     databases 16  数据库的数量 默认是16个
     always-show logo yes  是否显示logo
  快照
     持久化,在规定时间内,执行了多少次操作,则会持久化到文件.rdb .aof
     redis是内存数据库,如果没有持久化,那么数据断电就失去了     
     
     如果900秒内,如果至少有1个key进行了修改,我们就进行持久化操作
     save 900 1 
     save 300 10
     save 60 10000
     我们之后学习持久化,会自己定义

     stop-writes-on-bgsave-error yes 持久化如果出错,是否会继续工作
     rdbcompression yes 是否压缩rdb文件,这是需要消耗一些cpu资源
     rdbchecksum yes 保存rdb文件时,是否校验错误
     dir ./ rdb文件保存的目录 默认当前文件夹

  主从复制

  SECURITY安全 可以设置密码 默认是空的
      配置文件里设置密码requirepass 123456 
      config get requirepass 得到密码
      config set requirepass “123456” 命令设置密码
      auth 123456 登录
 

   限制 CLIENTS
      maxclients 10000 设置能链接上的最大客户端数量
      maxmemory <bytes> redis 配置最大的内存容量
      maxmemory-policy noeviction  内存达到上限之后的处理策略
  
   APPEND ONLY模式 aof配置
      appendonly no 默认不开启,默认是使用rdb方式持久化的,在大部分情况下,rdb完全够用
      appendfilename “”  持久化文件名字
      appendfsync always/eveysec/no 总是(每次修改都会sync,速度慢)/每秒(每秒执行一次sync,可能会丢失这1s数据)
                         /不执行(不执行sync,这个时候操作系统自己同步数据,速度最快)

18.rdb优点:
      1.适合大规模的数据恢复
      2.对数据的完整性要求不高
      缺点:
       1.需要一定的时间间隔进程操作,如果redis意外宕机了,这个最后一次修改的数据就没有了
       2.fork进程的时候,会占用一定的内存空间

   在生产环境,我们会将dump.rdb备份

   aof 将我们所有的命令都记录下来,history,恢复的时候将这个文件全部执行一边
       追加文件(无限追加,文件会越来越大)而不是改写文件 数据量大的时候效率低 
   如果aof文件有错误,redis是启动不起来的,redis提供了redis-check-aof来修复aof文件
   优点:
      1.每一次修改都同步,文件的完整性会更加好
      2.默认每秒同步一次,可能会丢失一秒的数据
      3.从不同步,效率最高
   缺点:
      1.相对于数据文件来说,aof远远大于rdb,修复的速度也比rdb慢
      2.aof运行效率比rdb慢,默认使用rdb

   在主从复制中,rdb就是备用了


19.redis发布订阅是一种消息通信模式:发送者pub发送信息,订阅者sub接受消息
   redis客户端可以订阅任意数量的频道 
   1.消息发送者 2.频道 3.消息订阅者

   发送端命令:PUBLISH 频道名 发布内容
   订阅端命令:SUBSCRIBE 频道名 
   发送端发送后,订阅端自动刷新监听到的内容
 

20.主从复制,读写分离。80%的情况下都是在进行读操作,减缓服务器压力在架构中经常使用
   最低配置一主二从
  
    概念:将一台服务器的数据,复制到其他的服务器。前者称为主节点,后者成为从节点
          数据的复制是单向的,只能由主节点到从节点,前者以写为主,后者以读为主
          默认情况下,每台redis服务器都是主节点,一个主节点可以有多个从节点或没有从节点,
           但是一个从节点只能有一个主节点
 
   主从复制的主要作用:
      数据冗余:实现了数据的热备份,是持久化之外的数据冗余凡是
      故障恢复:主节点出现问题,从节点提供服务
      负载均衡:主从复制的基础上,读写分离,主节点写操作,从节点读操作,多个从节点分担读负载
      高可用基石: 主从复制还是哨兵和集群能够实现的基础
   单台redis最大使用内存不应该超过20G
    
   主要在公司中,主从复制就是必须的

   环境配置:只配置从库,不配置主库    
       info replication 打印出当前库关于主从复制的信息
       多个配置文件:
            logfile “”名称不能重复
            dump.rdb 名称不能重复
            端口需要修改 pidfile也需要改成对应的
  

    一般情况下,只用配置从机就好了
     1.命令配置:
     slaveof 127.0.0.1.6379 认当前主机下的6379端口的redis为老大
     自己就变成了从机
     2.配置文件永久配置
     

     主机断开连接,从机依旧连接到主机,但是没有写操作,当主机恢复连接后,从机依旧保持连接
     如果使用命令行,来配置的主从,从机重启就会变回主机,从机重启后,拿不到主机数据
     重新设置为从机后,会立即从主机中获取到数据
     复制原理:
      slave启动成功连接到matser后会发送一个sync同步命令
      master接收到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台
      进程执行完毕后,master将传送整个数据文件到slave,并完成一次完全同步
        全量复制:而slave服务在接收到数据库文件数据后,将其存盘加载到内存中
        增量复制:Master继续将新的所有收集到的修改命令一次传给slave,完成同步
      但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

      链式主从时,如果主机断了,从机可以SLAVEOF no one让自己设为主机

21.哨兵模式
   哨兵模式是一种特殊的模式,首先redis提供了哨兵的命令,哨兵是一个独立的进程,
   作为进程,它会独立运行。其原理是哨兵通过发送命令,等待redis服务器响应,从而
   监控运行的多个redis实例

   sentinel monitor myredis 127.0.0.1 6379 1
                    服务器名 监视的主机端口 1代表有多少个哨兵认为该主机挂了就开始故障转移让其客观下线

   如果master节点断开了,这个时候就会随机从从机中选择一个服务器(这里有一个算法)
   failover故障转移  
   如果此时主机回来了,只能归并到新主机的从机

   优点:
     1.哨兵集群,基于主从复制模式,所有的主从配置优点,他全有
     2.主从可以切换,故障可以转移,系统的可用性就会更好
     3.哨兵模式就是主从模式的升级,手动到自动,更加健壮
   缺点:
     1.redis不好在线扩容,集群容量一旦到达上限,在线扩容就十分麻烦
     2.实现哨兵模式的配置其实是很麻烦的,里面有很多选择
 


22.redis缓存穿透(查不到导致的)和雪崩
   缓存穿透:
      用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,
      于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多时,
      缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力
      这时候就相当于出现了缓存穿透

   解决方案:
      布隆过滤器:
        是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,
        不符合则丢弃,从而避免了对底层存储系统的查询压力

      缓存空对象:
        当存储层不命中后,即使返回的空对象也将其缓存起来,同时设置一个过期时间,
        之后再访问这个数据将会从缓存中获取,保护了后端数据源
        存在的问题:
          1.空值被缓存起来,会占用更多的空间
          2.即使设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致
            这对需要保持一致性的业务会有影响

   
    缓存击穿(量太大,缓存过期导致的):
      一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key
        在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,并且回写缓存,会导致数据库瞬间压力过大
     

     解决方案:
      1.设置热点数据永不过期
      2.加互斥锁:
         分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有
          获得分布式锁的权限,因此只需要等待即可,但是对分布式锁的考验很大


    缓存雪崩:
      某一时间段,缓存集中过期失效/redis宕机/断网

   解决方案:

    redis高可用:多设几台redis
    限流降级:缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量
    数据预热:在正式部署之前,我先把可能的数据访问一边,这样部分可能大量访问的数据就会
           加载到混村中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的
           过期时间,让缓存失效的时间尽量均匀

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值