Redis

Database and Ruby, Python, History


安装

下载镜像docker pull redis

创建docker-compose.yml

docker-compose.yml

version: '2'
services:
  redis:
    image: redis:latest
    ports:
      - 6379:6379
    expose:
      - 6379

常用命令

进入redis

docker-compose up -d redis
docker exec -it 37d662e1d58e redis-cli

查看当前keys、key的类型

127.0.0.1:6379> keys *
1) "queue:mailer"
2) "stat:failed:2020-09-11"
3) "stat:processed:2020-09-11"
4) "queue:default"
5) "stat:failed"
6) "queues"
7) "stat:processed"
127.0.0.1:6379> dbsize
(integer) 7
127.0.0.1:6379> type quques
none
127.0.0.1:6379> type queues
set
127.0.0.1:6379> type queue:default
list

切换数据库

127.0.0.1:6379> config get databases
1) "databases"
2) "16"
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=7,expires=2,avg_ttl=149900461200
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
(empty array)
127.0.0.1:6379[1]> dbsize
(integer) 0
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> dbsize
(integer) 7

###清空当前数据库

flushdb

###清空所有数据库

flushall

操作字符串

127.0.0.1:6379> set name 'hello'
OK
127.0.0.1:6379> get name
"hello"
127.0.0.1:6379> append name ', world!'
(integer) 13
127.0.0.1:6379> get name
"hello, world!"
127.0.0.1:6379> mget name name
1) "hello, world!"
2) "hello, world!"
127.0.0.1:6379> ttl name
(integer) -1
127.0.0.1:6379> expire name 1
(integer) 1
127.0.0.1:6379> get name
(nil)

操作Hash

127.0.0.1:6379> HMSET king username forezp password xxdxx age 22
OK
127.0.0.1:6379> type king
hash
127.0.0.1:6379> hgetall king
1) "username"
2) "forezp"
3) "password"
4) "xxdxx"
5) "age"
6) "22"

操作列表

127.0.0.1:6379> lpush pricess kenny
(integer) 1
127.0.0.1:6379> lpush pricess [phoenix nova]
(integer) 3
127.0.0.1:6379> lrange pricess
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange pricess 0 -1
1) "nova]"
2) "[phoenix"
3) "kenny"
127.0.0.1:6379> rpush pricess gitlab
(integer) 4
127.0.0.1:6379> lrange pricess 0 -1
1) "nova]"
2) "[phoenix"
3) "kenny"
4) "gitlab"

无序集合

127.0.0.1:6379> sadd members sdk java j2ee
(integer) 3
127.0.0.1:6379> smembers members
1) "sdk"
2) "java"
3) "j2ee

有序集合

127.0.0.1:6379> ZADD kindom 1 redis
(integer) 1
127.0.0.1:6379> type kindom
zset
127.0.0.1:6379> ZADD kindom 2 mongodb
(integer) 1
127.0.0.1:6379> ZADD kindom 3 mysql
(integer) 1
127.0.0.1:6379> zrange kindom 0 -1
1) "redis"
2) "mongodb"
3) "mysql"
127.0.0.1:6379> zadd kindom 4 mysql
(integer) 0
127.0.0.1:6379> zrange kindom 0 -1
1) "redis"
2) "mongodb"
3) "mysql"
127.0.0.1:6379> zrange kindom 0 -1 withscores
1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

过期策略

定时删除

在设置key的时候,设置定时器,到期即删除。不过定时器会消耗资源,当key过多的时候,会消耗过多的CPU去查询哪些key需要删除。所以这个没有使用。

定期删除

在上述情况下,时间紧,任务重,就随机选择一部分删除就行了。

惰性删除

定期删除有个问题就是有些数据老是不会被删掉,只好在下次访问的时候,如果发现过期了,就删掉。

内存淘汰策略

就算有了上述这些方法,如果过期时间过长,没有等到清理之前,内存还是会被撑爆的。当内存不足时,就有8中内存淘汰策略。

  1. noeviction:新写入操作会报错。
  2. allkeys-lru:在所有键中,移除最近最少使用的key。
  3. allkeys-random:在所有键中,随机移除某个key。
  4. volatile-lru:在设置了过期时间的键空间中,移除最近最少使用的key。
  5. volatile-random:在设置了过期时间的键空间中,随机移除某个key。
  6. volatile-ttl:在设置了过期时间的键空间中,有更早过期时间的key优先移除。
  7. volatile-lfu:从配置了过期时间的键中删除使用频率最少的键
  8. allkeys-lfu:从所有键中删除使用频率最少的键

缓存击穿 && 布隆过滤器

有时候会遇到一种情况,即redis里面没有,数据库里面也没有。如果我们能够把不存在结果的情况也缓存起来,就更好了。这个时候需要启用布隆过滤器。 用上布隆过滤器以后,可以Redis有可以继续为数据库挡枪子了。

布隆过滤器

一般我们判断某个key是否存在于一个集合中,我们第一反应就是hash。通过hash函数和mod,我们可以很快的判断某个key是否存在于集合中。但是hash有个问题,就是存储效率不高。也就是说,如果集合过大的时候,会占用很大的空间。空间一大,要去查询也会随着更加耗时。

布隆过滤器能够占用hash存储空间的是1/4甚至1/8的空间,达到同样的效果。缺点就是会误判一些应该被标示为存在的,一般配合一个白名单即可。

缓存雪崩

程序上把一些热点数据也设置了时间,在某一时刻,过多的热点数据被清除掉,那缓存的意义就没有了。需要热点数据永不过期,临时数据过期时间随机。