redis是基于c语言的一个开源的非关系型数据库!!!!单线程的


1.常见的5种数据类型

1.1string

set key value 常见场景:数据库分表的id值,以及计数器(string类型的incr和decr命令:自增),计数器:如微博的评论数、点赞数、分享数,抖音作品的收藏数,京东商品的销售量、评价数等。

1.1.1sds讲解

redis的string内部格式如下:

struct sdshdr {
    // buf 已占用长度
    int len;

    // buf 剩余可用长度
    int free;

    // 实际保存字符串数据的地方
    char buf[];
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 所以可以看到变量len,也就说明了我们获取长度为O(1)
  • 并且也因为len,我们可以保存二进制文件,因为不在以/0为结尾判断,所以是Api安全;而c中的因为以/0为结尾判断,所以可能会丢失某些数据
  • 另外,对append函数的优化,c来说每次就会重新分配内存,而sds优化后,当不足的时候也会重新分配,但是同时会将free = len,也就说明了扩大了一倍容量,下次append的时候就不用再次分配,当然会有一些空间的损失,但是因为append一般不是很大所以还好。

注:真实看源码就知道这些大佬的牛!!!

1.2list:双向链表

lpush key value 常见场景:朋友圈点赞的展示,像这种有序的。

1.3hash

hset key filed value 常见场景:购物车,即 { 顾客: 商品1:数量, 商品2:数量 }

1.4set(存储大量数据)

sadd key value 常见场景:不重复 共同好友的推荐、同类信息的关联检索

1.5z_set(排序的set)

zadd key score1 value 常见场景: 范围查找、访问量的统计排序。

1.6bitmaps(位数组)

getbit key offset 常见场景: 一般用于是否点赞等等,并且布隆过滤器也是用的其存储,还有像位图法:从一个大量的数据中,找到某一些值,我们可以利用为数组,某一位存储一个数,则内存量大大降低。

<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

2.缓存问题

2.1.缓存雪崩

定义: 就是在同一时间内,有大量的key到期失效,所以都访问了数据库,从而导致数据库负载增加,甚至崩溃。

分析: 1)因为是同一时间段,大量的失效,说明可能是redis崩溃了或者是有大量的请求 2)或者是很多key设置的到期时间是差不多的

解决: 1.1)针对第一种,咱们可以设置集群来减轻redis服务器的压力。 1.2)针对第一种,还可以进行限流(限制客户端的连接数量):

  • 1:计数器 一定时间内只能有10个客户端来进行连接,然后不断的计时。
  • 2:令牌桶算法 java的定时任务也可以完成,简单思想就是:存在并维护一个list,加入一些值作为令牌,当有客户端来的时候,如果list有令牌,则可以进行访问;反之认为超出范围,拒绝访问。 比较:明显的来说,计时器关注时间,而令牌桶算法则关注连接量。

2)针对第二种,咱们可以对于其key的到期时间设置一个基础值+随机值,防止其同时到期。 <hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

2.2缓存穿透

定义: 访问大量的不存在的key,导致redis无法缓存,直接访问数据库,导致数据库访问量增大。

分析: 1)由于不存在的key,数据库没有,一般不会缓存

解决: 1)针对不存在的key,我们也缓存,但是必须设置一个到期时间,不然的话太浪费空间 2)布隆过滤器来解决:

  • 思路:多个hash,bitmap 当一个key查询来的时候,不同的hash分别得到一个值,然后%,分别在bitmap的响应位查看是否是0/1,如果有一个是0,则直接认为不合法,而肯定会有一些错判,但是我们可以增加使用一些高效的hash或者增加bitmap的容量。

注意:可能会有个疑问,数据什么时候写入呢,应该是当往数据库插入的时候,以及同步到缓存后。

Redis基本语法_redis

<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

2.3缓存击穿

定义: 不同于缓存雪崩,其主要是大量请求同一个失效的key/同一条数据,而缓存雪崩是不同的key。

分析: 主要是key失效,还是热点key

解决方法: 1)明显的解决方法就是增加其时间,或者说设置key永不失效 2)还有个策略就是对热点key进行加锁,保证同一时间内只有一个客户端访问它。但是加锁明显会降低效率,所以一般要慎用。

<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

2.4布隆过滤器失效key

  • 其实对于redis实现的布隆过滤器,我们无法单独的让一个key失效,而真正的做法,expire key 0,只能说这样整体会失效
  • 而对于一个值失效来说,我们需要自己手动实现一个布隆过滤器,这个布隆过滤器,在实现上要用一个计时器的功能,可以用Java自己模拟一个(简单说一下细节):
  • 1.定义一个类
  • 2.这个类有3-5个hash函数
  • 3.声明一个hashmap
  • 4.对于添加的每个数,进行hash函数生成,然后在hashmap的指定位置上,进行插入(数+个数)
  • 5.对于查询每个数,同理进行hash函数生成,如果有一个数不存在(值为0),则不存在;反之,存在
  • 6.对于删除一个数,同理进行hash函数生成,如果有一个数不存在(值为0),则不存在;反之,则在hashmap的指定位置上进行-1操作。