K/V数据库

redis用处

1.cache 缓存
2.简单队列 (lists)
3.排行榜 (zset:有序的集合)
4.计数场景

redis支持数据结构

strings(字符串)

string类型是二进制安全的,意味着redis的string可以包含任何数据,比如jpg图片或者序列化的对象
一个redis的字符串value最大可以是512M

数据结构

string数据结构为简单动态字符串,是可以修改的字符串,内部实现类似于java的arrayList,采用预分配冗余空间的方式来减少内存的频繁分配
string结构分配的空间一般要高于len,当小于1M时每次扩容会按当前空间加倍,当大于1M时则每次扩容增加1M,最大可存储512M

常用命令

1.设置值
set key value [EX SECONDS|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
NX:当数据库中key不存在时,可以将key-value添加数据库
XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
EX:key的超时时间,秒
PX:key的超时时间毫秒,与EX参数互斥
EXAT timestamp: 设置过期时间戳(秒级)
PXAT milliseconds-timestamp:设置过期时间戳(毫秒级)
KEEPTTL: 保留该key上次剩余的过期时间
2.获取值
get key
3.追加值,将value追加至原值末尾
append key value
4.获取值长度
strlen key
5.setnx key value (key不存在时设置key的值)
6.将key的数值增1,只能对数字操作,为空则新增为1
incr key
反之为decr key,将数值减一,为空则为-1
7.同6,但是可指定步长
incrby key 10(指增加10)
decrby key 10
8.批量操作(原子性,一个失败全失败)
mset key value key value
mget key key
msetnx key value key value (key不存在时设置key的值)
getrange key start end(获取key从start到end范围的值)
setrange key start value(从start开始对值进行更新,前面的值如不存在则默认为\x00)
9.获取旧值并设置新值
getset key value
10.设置有效期key
setex key seconds value

hash(哈希)

redis的hash是一个健值对组合
redis的hash是一个string类型的field和value的映射表,hash特别适合用来存储对象,类似于java中的Map

数据结构

hash对应的数据结构是两种:ziplist和hashtable,当field-value长度较短且数量少时使用ziplist,否则使用hasttable

常用命令

1.设置hash类型key(在redis4.0之前hset只能设置一个field value,在4.0之后hset等同于hmset)
hset key field value field value
2.获取hash类型key的值
hget key field
3.判断字段是否存在(1为存在,0为不存在)
hexists key field
4.获取key中所有field
hkeys key
5.获取key中所有value
hvals key
6.将key的field值加相应的(increment)数值
hincrby key field increment
7.当field不存在时可存储成功(1为成功,0为失败)
hsetnx user key field value

lists(列表)

单键多值
redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或尾部
它的底层实现是双向链表,对两端的操作性都很强,通过索引下表操作中间的的节点性能会较差

数据结构

list数据结构是一个快速链表(quicklist)
首先在元素少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表
他将所有元素紧挨着存储,是一块连续的内存
当元素多的时候才会改为quicklist
因为普通的链表需要的附加指针空间太大,会比较费空间,比如这个列表中只存储了int类型的数据,还要增加l两个指针next和prev
image.png

redis将链表和ziplist结合起来组成了quicklist,也就是多个ziplist使用双向指针串起来使用,这样既满足了快速插入删除性能,也不会有太多的冗余空间。

常用命令

1.从左边或右边插入一个或多个值
lpush/rpush key value value valule
2.从左边或右边吐出一个值,值在健在,值光健亡
lpop/rpop key
3.从key1左边吐出一个值插入key2右边,反之亦可
lpoprpush key1 key2
rpoplpush key1 key2
4.从左边按索引下标获取元素,反之从右边不可
lrange key start end
lrange key 0 -1 (0代表左边第一个,-1代表右边第一个,获取全量)
5.从左边通过下标获取元素
lindex key 0
6.获取key的长度
llen key
7.从某个value前或后查询新value,若该value存在多个只会在从左数第一个元素前或后新增
linsert key BEFORE|AFTER value newvalue
8.从左边开始删除n个与value相同的元素,n为0表示删除所有
lrem key n value
9.将某个下标的元素替换成新元素
lset key index value

sets(集合,无序,不重复)

redis的set对外提供的功能与list类似是一个列表的功能,特殊之处在于set可以自动排重,当你需要存储一个列表数据,又不希望出现重复数据,set是一个很好的选择。并且set提供了一个判断元素是否存在的接口,这个是list所没有的
redis的set是string类型的无序集合,他的底层是一个value为null的hash表,所以添加,删除、查找的复杂度为0(1)

数据结构

set的数据结构是dict(字典),字典使用哈希表实现的

常用命令

1.添加一个或多个元素
sadd key value value value
2.获取key中所有元素
smembers key
3.判断元素是否存在,存在返回1,不存在返回0
sismember key value
4.获取key中元素个数
scard key
5.删除集合中一个或多个元素
srem key value value
6.随机吐出一个元素
spop key
7.随机吐出n个元素,并且不会删除
srandmember key n
8.将一个集合元素移入另一个集合中
smove key1 key2 value
9.返回两个集合的交集
sinter key1 key2
10.返回两个集合的并集
sunion key1 key2
11.返回两个集合的差集(key1中,不包含key2)
sdiff key1 key2

zset(带范围查询的排序集合)

redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。
不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复的。
因为元素是有序的,所以你也可以很块的根据评分(score)或者次序(position)来获取一个范围的元素。
访问有序集合的中环元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表

数据结构

zset是redis提供的一个非常特别的数据结构,一方面它等价于java的数据结构Map,可以给每个元素value都赋予一个权重score,另一方面他又类似于TreeSet,内部元素会按照权重score进行排序,可以得到每个元素的名词,还可以通过score的范围来获取元素的列表。
zset的底层使用了两种数据结构:
1.hash,hash的作用是关联元素和权重score,保障value的唯一性,可以通过元素value找到score
2.跳跃表,跳跃表的目的在于给元素的value排序,根据score的范围获取元素列表

常用命令

1.将一个或多个member元素及其score值加入有序集合zset中(注意score位置在key前面)
zadd key score1 value1 score2 value2
2.输出有序集合key中,下标在start stop之间的元素,withsocres可以让分数和值一起返回,rev可以改为降序
zrange key start top [WITHSCORES] [rev]
3.返回有序集key中,所有score值介于min和max之间(包括等于min和max)的成员,按从小打到排序,limit表示分页,输入limit后offset和count必须指定
zrangebyscore key min max [withscores] [limit offset count]
分页
zrangebyscore key min max [withscores] limit 0 10
4.将如上效果按从大到小排序(注意max min和上面的位置相反)
zrevrangebyscore key max min [withscores] [limit offset count]
5.将元素的score加上增量
zincrby key incrment value
6.删除集合下指定元素
zrem key value
7.统计集合内分区内元素个数
zcount key min max
8.返回元素在集合内的排名,从零开始
zrank key value
9.获取指定元素的分数
zscore key value
10.获取key的总元素
zcard key

新数据类型(Bitmaps)

通过位置(下标)来操作数据,存储数值只能为0,1,多用来表示用户在线访问等

常用命令

1.设置key的值
setbit key offset value
2.获取key的值
getbit key offset
3.统计key中范围下标中,下标对应值为1的个数
bitcount key start end
4.复合操作,and(交集),or(并集),求key1和key2的交集、并集或将结果方置key3中
bitop and/or key3 key1 key2
5.求key1和key2的并集的相反值,并将结果方置key3
bitop xor key3 key1 key2
5.求key1的相反值,并将结果方置key3
bitop not key3 key1

新数据类型(HyperLogLog)

类似于set值不可重复,区别是set会存储元素的值,HyperLogLog主要是计数,通过对值进行hash使用hash对比,可快速计算出不重复元素的数量

常用命令

1.添加元素,如果元素不存在则返回1,存在返回0
pfadd key value value
2.计算key中的元素个数
pfcount key
3.合并k1 k2为一个key3
pfmerge key3 k1 k2

新数据类型(Geospatial)

主要应用于经纬度,地理位置的数据存储操作

常用命令

1.添加一个key为city的经纬度数据,值为经度、维度、地区
geoadd key 11.11 22.22 shanghai 22.22 33.33 beijing
2.获取key中地区的经纬度信息
geopos key beijing shanghai
3.获取地区之间的距离
geodist key beijing shanghai [m|km|mi|ft]
单位:
m 表示单位米(默认值)
km 表示单位km
mi 表示单位英里
ft 表示单位英尺
4.获取某一个经纬度一定距离内的地区
georadius key 11.11 22.22 1000(距离值) [m|km|mi|ft]

Redis安装

  1. 前置依赖
  2. yum -y install gcc gcc-c++ libstdc++-devel
  3. 1.编译
  4. cd /tools/redis-6.2.6
  5. make
  6. cd ./src && make install
  7. 2.配置redis
  8. mkdir -p /tools/redis-6.2.6/bin
  9. mkdir -p /tools/redis-6.2.6/etc
  10. mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-server /tools/redis-6.2.6/bin/
  11. cp /root/redis-6.2.6/redis.conf /tools/redis-6.2.6/etc/
  12. vim /tools/redis-6.2.6/etc/redis.conf
  13. #注释bind,取消只能本机访问
  14. #bind 127.0.0.1 -::1
  15. #关闭protected-mode模式
  16. protected-mode no
  17. #指定redis使用守护线程的方式启动,不需要再加&符号
  18. daemonize yes
  19. #指定密码
  20. requirepass 123456
  21. 3.启动redis
  22. cd /tools/redis-6.2.6/bin
  23. ./redis-server /tools/redis-6.2.6/etc/redis.conf
  24. 4.客户端连接
  25. /tools/redis-6.2.6/bin/redis-cli
  26. 5.认证
  27. 127.0.0.1:6379> auth 123456

安装目录

redis-benchmark:性能测试工具,可以在机子本机运行,看看自己本纪性能如何
redis-check-aof:修复有问题的AOF文件
redis-check-dump:修复有问题的dump.rdb文件
redis-sentinel:redis集群使用
redis-server:redis服务器启动命令
redis-cli:客户端,操作入口

常用命令

1.获取所有key(可进行通配,数据量很小的时候可以使用,生产环境极不推荐。会引起阻塞,严重的话会引起应用程序出现雪崩)
KEYS
keys aa

keys bb
2.获取string类型某个key的值
get key
3.设置值
规则如下:
set key value [EX SECONDS|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
#设置key为test值为string,有效期为5秒
set test “测试” EX 5
4.判断某个key是否存在
exists key
5.删除指定key
del key
6.根据value选择非阻塞删除(仅将key从keysapce元数据中删除,真正的删除会在后续异步执行)
unlink key
7.为key设置过期时间,10秒
expire key 10
8.查看key还有多久过期,-1表示永不过期,-2表示已过期
ttl key
9.查看当前数据库的key数量
dbsize
10.查看key的类型
type key
11.获取zset类型某个key的值
#获取排行0-100
zrange language_rank 0 100
#输出score
zrange language_rank 0 100 withscore
#倒排从高到低
zrange language_rank 0 100 rev withscores
12.切换库,默认为库0
select dbid
示例: select 0
13.清空当前库
flushdb
14.清空所有库
flushall
15.查看所有库key数量
info keyspace

GO操作redis

安装

go get -u github.com/go-redis/redis

使用

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/go-redis/redis"
  5. "time"
  6. )
  7. var redisDb *redis.Client
  8. func initRedis() (err error) {
  9. redisDb = redis.NewClient(&redis.Options{
  10. Addr: "192.168.72.10:6379",
  11. Password: "123456",
  12. DB: 0,
  13. })
  14. _, err = redisDb.Ping().Result()
  15. if err != nil {
  16. fmt.Println("redis client conn err", err)
  17. return
  18. }
  19. return
  20. }
  21. func stringExample() {
  22. //存储一个key为test的值,有效期为5秒
  23. err := redisDb.Set("test", "哈哈", 5*time.Second).Err()
  24. if err != nil {
  25. fmt.Println("set err", err)
  26. }
  27. ret, err := redisDb.Get("test").Result()
  28. if err != nil {
  29. fmt.Println("get err", err)
  30. }
  31. fmt.Println(ret)
  32. }
  33. func zSetExample() {
  34. zKey := "language_rank"
  35. items := []redis.Z{
  36. redis.Z{Score: 99.0, Member: "Java"},
  37. redis.Z{Score: 98.0, Member: "Go"},
  38. redis.Z{Score: 97.0, Member: "Python"},
  39. }
  40. num, err := redisDb.ZAdd(zKey, items...).Result()
  41. if err != nil {
  42. }
  43. fmt.Println(num)
  44. //给某个member加10分
  45. newScore,err := redisDb.ZIncrBy(zKey, 10.0, "Java").Result()
  46. if err != nil {
  47. }
  48. fmt.Println(newScore)
  49. //去最高的三位
  50. ret,err:=redisDb.ZRevRangeWithScores(zKey,0,3).Result()
  51. if err != nil {
  52. }
  53. fmt.Println(ret)
  54. }
  55. func main() {
  56. initRedis()
  57. //stringExample()
  58. zSetExample()
  59. }