Java-Redis-进阶

一、Java-Redis-进阶

1.1 SDS(动态字符串)

struct sdshdr{
 int len;
 int free;
 char buf[];
}
image.png
  • 空间预分配:当我们对SDS进行扩展操作的时候,Redis会为SDS分配好内存,并且根据特定的公式,分配多余的free空间,还有多余的1byte空间(这1byte也是为了存空字符),这样就可以避免我们连续执行字符串添加所带来的内存分配消耗
  • 惰性空间释放:当我们执行完一个字符串缩减的操作,redis并不会马上收回我们的空间,因为可以预防你继续添加的操作,这样可以减少分配空间带来的消耗,但是当你再次操作还是没用到多余空间的时候,Redis也还是会收回对于的空间,防止内存的浪费的。

1.2 skiplist(跳跃表)

  每一个节点的层数(level)是随机出来的,而且新插入一个节点并不会影响到其他节点的层数,因此,插入操作只需要修改节点前后的指针,而不需要对多个节点都进行调整,这就降低了插入操作的复杂度。

image.png
image.png
int zslRandomLevel(void) {
    int level = 1;
    while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
        level += 1;
    return (level

  直观上期望的目标是50%的概率被分配到Level 1,25%的概率被分配到Level 2,12.5%的概率被分配到Level 3,以此类推。每一层的晋升率都是 50%Redis 跳跃表默认允许最大的层数是32

1.3 Redis慢日志

# 命令执行耗时超过 5 毫秒,记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近 500 条慢日志
CONFIG SET slowlog-max-len 500
# 查看
SLOWLOG get 5
  • 经常使用O(N) 以上复杂度的命令,例如 SORT、SUNION、ZUNIONSTORE 聚合类命令
  • 使用O(N) 复杂度的命令,但N的值非常大

1.4 bigKey

--bigkeys -i 0.01
  • 对线上实例进行bigkey扫描时,Redis的OPS会突增,为了降低扫描过程中对Redis的影响,最好控制一下扫描的频率,指定-i参数即可,它表示扫描过程中每次扫描后休息的时间间隔,单位是秒。
  • 扫描结果中,对于容器类型(List、Hash、Set、ZSet)的 key,只能扫描出元素最多的 key。但一个 key的元素多,不一定表示占用内存也多,你还需要根据业务情况,进一步评估内存占用情况。
  • 业务应用尽量避免写入bigkey
  • 扫描分片,业务隔离
  • Redis是4.0以上版本,用UNLINK命令替代DEL,此命令可以把释放key内存的操作,放到后台线程中去执行,从而降低对Redis的影响
  • Redis是6.0以上版本,可以开启lazy-free机制(lazyfree-lazy-user-del = yes),在执行DEL命令时,释放内存也会放到后台线程中执行

1.5 fork耗时严重

# 上一次 fork 耗时,单位微秒
latest_fork_usec:59477
image.png

1.6 缓存一致性问题

  先删缓存,再更新数据库:先删除缓存,数据库还没有更新成功,此时如果读取缓存,缓存不存在,去数据库中读取到的是旧值,缓存不一致发生。

image.png

  延时双删的方案的思路是,为了避免更新数据库的时候,其他线程从缓存中读取不到数据,就在更新完数据库之后,再sleep一段时间,然后再次删除缓存

  • 线程1删除缓存,然后去更新数据库
  • 线程2来读缓存,发现缓存已经被删除,所以直接从数据库中读取,这时候由于线程1还没有更新完成,所以读到的是旧值,然后把旧值写入缓存
  • 线程1,根据估算的时间,sleep,由于sleep的时间大于线程2读数据+写缓存的时间,所以缓存被再次删除
  • 如果还有其他线程来读取缓存的话,就会再次从数据库中读取到最新值
image.png

  先更新数据库,再删除缓存:更新数据库成功,如果删除缓存失败或者还没有来得及删除,那么,其他线程从缓存中读取到的就是旧值,还是会发生不一致。

image.png
image.png
  • 每次放入缓存的时候,设置一个过期时间,比如5分钟,以后的操作只修改数据库,不操作缓存,等待缓存超时后从数据库重新读取

1.7 其他

一个架构师的缓存修炼之路
redis预估内存应用案例
Redis容量评估

你可能感兴趣的:(Java-Redis-进阶)