Redis的优点:
(一)纯内存操作,避免大量访问数据库,减少直接读取磁盘数据,redis将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度快;
(二)单线程操作,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
(三)采用了非阻塞I/O多路复用机制
原子性 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。(详细)https://blog.csdn.net/weixin_42075590/article/details/80869063
缺点:redis存储成本高
redis是单线程的,单台服务器无法充分利用多核服务器的CPU
由于 Redis 是内存数据库,所以,单台机器,存储的数据量,跟机器本身的内存大小。虽然 Redis 本身有 Key 过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据
- 缓存和数据库双写一致性问题
- 缓存雪崩问题 (redis设置时间,到时间之后自动删除数据。导致大量的访问直接打到sql数据库中导致雪崩)
- 缓存击穿问题 (一般是不会发生,但是恶意使用特殊数据,比如0.几,负数。redis中没有对应的值直接访问数据库)
Redis适用场景?
1.队列(秒杀,抢购,12306)list数据类型的使用
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。2.热点资源,需要经常获取的值。和一些数据不经常变化的值。
3.排行榜/计数器(set数据类型的使用)
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。
redis基本操作
一、Sting
set key value #插入数据
get key #获取数据
del key #删除数据
127.0.0.1:6379> set name aad OK 127.0.0.1:6379> get name "aad" 127.0.0.1:6379> del name (integer) 1
getrange key start end #获取key一段值
127.0.0.1:6379> set name aaa OK 127.0.0.1:6379> GETRANGE name 0 2 "aaa" 127.0.0.1:6379> GETRANGE name 0 1 "aa"
keys pattern #查看key
127.0.0.1:6379> keys * 1) "user:1:views" 2) "user:2:age" 3) "name" 4) "mykey" 5) "list" 6) "age" 7) "user:1:name" 8) "mylist" 9) "myotherlist" 127.0.0.1:6379> keys m* 1) "mykey" 2) "mylist" 3) "myotherlist" 127.0.0.1:6379> keys pattern
incr key #自增
127.0.0.1:6379> set key 1 OK 127.0.0.1:6379> INCR key (integer) 2
incrby key increment #自己设置增加的值
127.0.0.1:6379> get key "220" 127.0.0.1:6379> incrby key 10 (integer) 230
append key value #对已经存在的字符串的key再次进行拼接。
127.0.0.1:6379> append key 111 (integer) 6 127.0.0.1:6379> get key "230111"
setnx key value #分布式锁
127.0.0.1:6379[15]> setnx job program (integer) 1 127.0.0.1:6379[15]> setnx job ada (integer) 0 127.0.0.1:6379[15]> get job "program"
二、哈希HASH
hset key field value #插入一个哈希结构字段
hkeys key #获取hash map 中的key值
hvals key #取hash map 中的value值
hget key field # 获取value值
127.0.0.1:6379> hset name1 a csd (integer) 1 127.0.0.1:6379> hkeys name1 1) "a" 127.0.0.1:6379> hvals name1 1) "csd" 127.0.0.1:6379> hget name1 a "csd"
hmset key field value field value #设置多个哈希字段
127.0.0.1:6379> hmset name2 a1 323 a2 4232 a3 4244 OK 127.0.0.1:6379> hget name2 a1 "323" 127.0.0.1:6379> HKEYS name2 1) "a1" 2) "a2" 3) "a3"
hlen key # 获取哈希表中的字段数
127.0.0.1:6379> hlen name2 (integer) 3
hsetnx key field value #只有字段filed 不存在时才可以插入0插入失败,1成功
127.0.0.1:6379> hsetnx name3 da aaa (integer) 1 127.0.0.1:6379> hsetnx name2 aa aaa (integer) 1 127.0.0.1:6379> hsetnx name2 aa aa (integer) 0 127.0.0.1:6379>
三、列表List
lpush key value value value #插入数据到数组中
LRANGE key start end #查询数组,-1全显示
127.0.0.1:6379[2]> LPUSH name aad ddc aac bbc (integer) 4 127.0.0.1:6379[2]> LRANGE name 0 -1 1) "bbc" 2) "aac" 3) "ddc" 4) "aad"
rpush key value1 value2 value3 #从右边插入
127.0.0.1:6379> rpush listright aa bb cc (integer) 3 127.0.0.1:6379> LRANGE listright 0 -1 1) "aa" 2) "bb" 3) "cc" 127.0.0.1:6379>
llen key #获取数组的长度
lpushx key value #插入数据到已有的数组中,没有就不行
127.0.0.1:6379[2]> llen name (integer) 4 127.0.0.1:6379[2]> lpushx name dada (integer) 5
lrem key count value #删除数组的几个元素
127.0.0.1:6379[2]> lrem name 2 aac (integer) 1 127.0.0.1:6379[2]> lrem name 0 aab (integer) 0
lset key index value #修改数组下标对应的值
127.0.0.1:6379[2]> lset name 1 211 OK 127.0.0.1:6379[2]> LRANGE name 0 -1 1) "dada" 2) "211" 3) "ddc" 4) "aad"
rpop key #移除数组最后一个值
127.0.0.1:6379[2]> rpop name "aad"
rpoplpush key1 key2 #把key1中的最后一个值移动到key2中
127.0.0.1:6379> RPOPLPUSH mylist otherlist "hellow2" 127.0.0.1:6379> lrange mylist 0 -1 1) "hellow" 2) "hellow1" 127.0.0.1:6379> LRANGE otherlist 0 -1 1) "hellow2"
lindex key index #查询 数组的某个值
127.0.0.1:6379> lpush list aaa bbb ccc dd e (integer) 5 127.0.0.1:6379> LINDEX list 2 "ccc"
linsert key before/after value element
127.0.0.1:6379> LINSERT list before ccc aa (integer) 6
四、集合
sadd key value value #插入数据到集合(去重)
scard key #查看集合元素个数
smembers key #查看集合元素
127.0.0.1:6379[3]> sadd runsetkey redis (integer) 1 127.0.0.1:6379[3]> scard runsetkey (integer) 1 127.0.0.1:6379[3]> SMEMBERS runsetkey
spop key count #随机移除元素
127.0.0.1:6379[3]> SMEMBERS setkey1 1) "aaaa" 2) "bbb" 3) "ccc" 4) "ee" 5) "sss" 6) "ddd" 127.0.0.1:6379[3]> spop setkey1 4 1) "ee" 2) "ccc" 3) "ddd" 4) "sss" 127.0.0.1:6379[3]> SMEMBERS setkey1 1) "bbb" 2) "aaaa"
srandmemer key count #随机返回元素
127.0.0.1:6379[3]> SMEMBERS setkey1 1) "ccd" 2) "ac" 3) "bbb" 4) "aaaa" 5) "ssd" 6) "sad" 127.0.0.1:6379[3]> SRANDMEMBER setkey1 2 1) "bbb" 2) "sad" 127.0.0.1:6379[3]>
srem key #移除集合中 指定的元素
127.0.0.1:6379[3]> SMEMBERS setkey1 1) "ccd" 2) "ac" 3) "bbb" 4) "aaaa" 5) "ssd" 6) "sad" 127.0.0.1:6379[3]> srem setkey1 ccd ac (integer) 2 127.0.0.1:6379[3]> SMEMBERS setkey1 1) "bbb" 2) "aaaa" 3) "ssd" 4) "sad"
sunion key1 key2 ... #并集
127.0.0.1:6379[3]> SMEMBERS setkey1 1) "bbb" 2) "aaaa" 3) "ssd" 4) "sad" 127.0.0.1:6379[3]> SMEMBERS setkey2 1) "ccd" 2) "sss" 3) "asd" 127.0.0.1:6379[3]> SUNION setkey1 setkey2 1) "sad" 2) "bbb" 3) "ccd" 4) "asd" 5) "aaaa" 6) "sss" 7) "ssd"
sinter key1 key2 #获取两个集合的交集
127.0.0.1:6379[3]> SMEMBERS setkey2 1) "ccd" 2) "sss" 3) "asd" 127.0.0.1:6379[3]> SMEMBERS setkey1 1) "sss" 2) "ccd" 3) "wyl" 127.0.0.1:6379[3]> SINTER setkey1 setkey2 1) "sss" 2) "ccd"
smove key1 key2 value #从key1中移动数据到key2(key2中已有相同数据也可以执行)
127.0.0.1:6379[3]> smove setkey1 setkey2 ssd (integer) 1 127.0.0.1:6379[3]> SMEMBERS setkey2 1) "ssd" 2) "ccd" 3) "sss" 4) "asd"
sdiff key1 key2 key3 #查询第一个集合中特有的元素(只有key1有的元素)
127.0.0.1:6379> sadd name ccd aab (integer) 2 127.0.0.1:6379> sadd name1 ccd aab (integer) 2 127.0.0.1:6379> sadd name2 ccd aab d (integer) 3 127.0.0.1:6379> sdiff name2 name name1 1) "d" 127.0.0.1:6379> sdiff name name2 name1 (empty array)
五、有序集合
zadd key index value index value ... #添加数据到有序集合中
127.0.0.1:6379[15]> zadd zedking 1 add 2 ccd 3 wyl (integer) 3
zrange key start end # 查看在一段范围中的集合元素
127.0.0.1:6379[15]> ZRANGE zedking 0 -1 1) "add" 2) "ccd" 3) "wyl"
zcount key start end #查看在一段范围中的集合元素个数
127.0.0.1:6379[15]> zcount zedking 0 2 (integer) 2 127.0.0.1:6379[15]> zcount zedking 0 4 (integer) 3
zincrby key index value #插入数据到集合中
127.0.0.1:6379[15]> ZINCRBY zedking 4 www "4" 127.0.0.1:6379[15]> ZRANGE zedking 0 -1 1) "add" 2) "ccd" 3) "wyl" 4) "www" 127.0.0.1:6379[15]> ZINCRBY zedking 0 index "0" 127.0.0.1:6379[15]> ZRANGE zedking 0 -1 1) "index" 2) "add" 3) "ccd" 4) "wyl" 5) "www"
Other
exists key #查询key是否已经被创建
setnx #创建一个新的string,已经存在就创建失败。
setex key time value #创建一个string类型的时间为time(秒)的字段
dbsize #查询数据库中的字段个数
select index #切换数据库 0-15
flushdb #清空当前数据库
flushall #清空所有数据库
Hyperloglog基数统计
内存占用量小仅仅12k。功能和set相似(去重),只能插入数据,统计数据。不能返回已有数据内容。一般用来统计登录个数(只统计个数,不记录具体用户信息)。
pfadd key value value1 value2 value3 #插入数据
pfcount key #统计key的个数
pfmerge key3 key1 key2 #把key1 key2 的值合并到key3去重
127.0.0.1:6379[2]> pfadd mykey a b c d e f g h i (integer) 1 127.0.0.1:6379[2]> pfadd mykey2 i o p e v (integer) 1 127.0.0.1:6379[2]> pfcount mykey (integer) 9 127.0.0.1:6379[2]> pfcount mykey2 (integer) 5 127.0.0.1:6379[2]> pfmerge mykey3 mykey mykey2 OK 127.0.0.1:6379[2]> pfcount mykey3 (integer) 12
geospatial
geoadd map 经度 纬度 命名
127.0.0.1:6379[4]> GEOADD map 86.07893 44.30653 石河子 (integer) 1 127.0.0.1:6379[4]> GEOADD map 121.84431 29.89889 宁波 (integer) 1 127.0.0.1:6379[4]> GEOADD map 121.1572 27.83616 温州 (integer) 1 127.0.0.1:6379[4]> GEOADD map 121.48941 31.40527 上海
zrange key start end #查看数据(中文导致乱码)
127.0.0.1:6379[4]> zrange map 0 -1 1) "\xe7\x9f\xb3\xe6\xb2\xb3\xe5\xad\x90" 2) "\xe6\xb8\xa9\xe5\xb7\x9e" 3) "\xe5\xae\x81\xe6\xb3\xa2" 4) "\xe4\xb8\x8a\xe6\xb5\xb7"
geopos key value1 value2 .. #获取value经纬度
127.0.0.1:6379[4]> geopos map 温州 1) 1) "121.15720242261886597" 2) "27.83615949067253581"
geodist key value1 value2 km/m/ft/mi #比较两地的距离 ( ft 表示单位为英尺,mi 表示单位为英里)
127.0.0.1:6379[4]> GEODIST map 温州 石河子 km "3607.2942" 127.0.0.1:6379[4]> GEODIST map 温州 石河子 m "3607294.1688"
Bitmaps
位储存 0 1 0 1
两个状态都可以使用bitmaps
setbit key index value #插入数据(value 只能0或1,输入2会报错)
getbit key index #获取数据、
bitcount key #统计key字段的1的个数
127.0.0.1:6379> setbit sign 2 1 (integer) 0 127.0.0.1:6379> setbit sign 2 0 (integer) 1 127.0.0.1:6379> getbit sign 2 (integer) 0 127.0.0.1:6379> bitcount sign (integer) 1