Redis 是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的 Web 应用程序。Redis 也被作者戏称为数据结构服务器 ,这意味着使用者可以通过一些命令,基于带有 TCP 套接字的简单服务器-客户端 协议来访问一组可变数据结构 。(在 Redis 中都采用键值对的方式,只不过对应的数据结构不一样罢了)。
进入redis客户端:
redis-cli -a -c -h -p // -a访问服务端密码,-c表示集群模式,-h指定主机ip,指定端口号)
redis-cli // 本机6379 无密码 单体模式
redis-cli -a 123456 -p 6374 -c // 本机6374 密码123456 集群模式
1.基本操作
Redis 默认有 16 个库(0-15),可以在配置文件中修改,默认使用第一个 db0;因为没有完全隔离,不像数据库的 database,不适合把不同的库分配给不同的业务使用。
切换数据库
select 0
清空当前数据库
flushdb
清空所有数据库
flushall
存值(key 和 value 的最大长度限制 是 512M)
set zhangsan 123
取值
get zhangsan
查看所有键
keys *
获取键总数
dbsize
查看键是否存在
exists zhangsan
删除键
del zhangsan
重命名键
rename zhangsan lisi
查看类型
type zhangsan
2.数据类型
Redis 有 5 种基础数据结构,它们分别是:string(字符串)、list(列表:队列/栈)、hash(字典)、set(集合:随机队列) 和 zset(有序集合)。这 5 种是 Redis 相关知识中最基础、最重要的部分,下面我们说一下它们基本的操作命令和应用场景。
关于这五种数据类型的基本命令、应用场景以及存储原理,请看专栏后面几篇文章…
对象 | 对象 type 属性值 | type 命令输出 | 底层可能的存储结构 | object encoding |
---|---|---|---|---|
字符串对象 | OBJ_STRING | “string” | OBJ_ENCODING_INT OBJ_ENCODING_EMBSTR OBJ_ENCODING_RAW | int embstr raw |
哈希对象 | OBJ_HASH | “hash” | OBJ_ENCODING_ZIPLIST OBJ_ENCODING_HT | ziplist hashtable |
列表对象 | OBJ_LIST | “list” | OBJ_ENCODING_ZIPLIST OBJ_ENCODING_LINKEDLIST OBJ_ENCODING_QUICKLIST | ziplist linkedlist quicklist(3.2后) |
集合对象 | OBJ_SET | “set” | OBJ_ENCODING_INTSET OBJ_ENCODING_HT | intset hashtable |
有序集合对象 | OBJ_ZSET | “zset” | OBJ_ENCODING_ZIPLIST OBJ_ENCODING_SKIPLIST | ziplist skiplist(包含 ht) |
3.存储原理
因为 Redis 是 KV 的数据库,它是通过 hashtable 实现的(我们把这个叫做外层的哈希)。所以每个键值对都会有一个 dictEntry(源码位置:dict.h), 里面指向了 key 和 value 的指针,next 指向下一个 dictEntry
typedef struct dictEntry {
/* key 关键字定义 */
void *key;
union {
/* value 定义 */
void *val; uint64_t u64;
int64_t s64; double d;
} v;
/* 指向下一个键值对节点 */
struct dictEntry *next;
} dictEntry;
其中,因为 key 都是字符串,所以 key 的底层结构就直接是 SDS;而 value 的话,是被 redisObject 这个结构进行了再次封装
typedef struct redisObject {
/* 对象的类型,包括:OBJ_STRING、OBJ_LIST、OBJ_HASH、OBJ_SET、OBJ_ZSET */
unsigned type:4;
/* 具体的数据结构 */
unsigned encoding:4;
/* 24 位,对象最后一次被命令程序访问的时间,与内存回收有关 */
unsigned lru:LRU_BITS;
/* 引用计数。当 refcount 为 0 的时候,表示该对象已经不被任何对象引用,则可以进行垃圾回收了 */
int refcount;
/* 指向对象实际的数据结构 */
void *ptr;
} robj;