Redis键值设计

小红书高时效推荐系统背后的技术升级 在小红书 APP 中,推荐系统的实效性对推荐效果有着特别重要的影响,特别是作为 UGC 平台,小红书的推荐系统如果能更快地捕捉用户与笔记之间的变化和联系,就能够给推荐带来更好的效果。在2021年上半年,首页推荐的召回、粗排、精排的主要模块都保持在天级更新的状态,我们通过持续迭代,将召回 CF 渠道、召回索引更新、召回模型/粗精排模型的训练都做到了分钟级更新,为首页推荐的分发效率带来飞跃式提升,并给业务侧带来非常显著的收益。 小红书站内“最近一天内发布的新笔记”在首页的曝光占比一直很高,这段时间更是快速 阅读详情
丰富的数据结构使得redis的设计非常的有趣。不像关系型数据库那样,DEV和DBA需要深度沟通,review每行sql语句,也不像memcached那样,不需要DBA的参与。redis的DBA需要熟悉数据结构,并能了解使用场景。

下面举一些常见适合kv数据库的例子来谈谈键值的设计,并与关系型数据库做一个对比,发现关系型的不足之处。

用户登录系统

记录用户登录信息的一个系统, 我们简化业务后只留下一张表。

关系型数据库的设计
mysql> select * from login;
+---------+----------------+-------------+---------------------+
| user_id | name           | login_times | last_login_time     |
+---------+----------------+-------------+---------------------+
|       1 | ken thompson   |           5 | 2011-01-01 00:00:00 |
|       2 | dennis ritchie |           1 | 2011-02-01 00:00:00 |
|       3 | Joe Armstrong  |           2 | 2011-03-01 00:00:00 |
+---------+----------------+-------------+---------------------+

user_id表的主键,name表示用户名,login_times表示该用户的登录次数,每次用户登录后,login_times会自增,而last_login_time更新为当前时间。

REDIS的设计

关系型数据转化为KV数据库,我的方法如下:

key 表名:主键值:列名

value 列值

一般使用冒号做分割符,这是不成文的规矩。比如在php-admin for redis系统里,就是默认以冒号分割,于是user:1 user:2等key会分成一组。于是以上的关系数据转化成kv数据后记录如下:

Set login:1:login_times 5
Set login:2:login_times 1
Set login:3:login_times 2

Set login:1:last_login_time 2011-1-1
Set login:2:last_login_time 2011-2-1
Set login:3:last_login_time 2011-3-1

set login:1:name ”ken thompson“
set login:2:name “dennis ritchie”
set login:3:name ”Joe Armstrong“

这样在已知主键的情况下,通过get、set就可以获得或者修改用户的登录次数和最后登录时间和姓名。

一般用户是无法知道自己的id的,只知道自己的用户名,所以还必须有一个从name到id的映射关系,这里的设计与上面的有所不同。

set "login:ken thompson:id"      1
set "login:dennis ritchie:id"    2
set "login: Joe Armstrong:id"    3

这样每次用户登录的时候业务逻辑如下(python版),r是redis对象,name是已经获知的用户名。

1 #获得用户的id
2 uid = r.get("login:%s:id" % name)
3 #自增用户的登录次数
4 ret = r.incr("login:%s:login_times" % uid)
5 #更新该用户的最后登录时间
6 ret = r.set("login:%s:last_login_time" % uid, datetime.datetime.now())

如果需求仅仅是已知id,更新或者获取某个用户的最后登录时间,登录次数,关系型和kv数据库无啥区别。一个通过btree pk,一个通过hash,效果都很好。

假设有如下需求,查找最近登录的N个用户。开发人员看看,还是比较简单的,一个sql搞定。

1 select * from login order by last_login_time desc limit N

DBA了解需求后,考虑到以后表如果比较大,所以在last_login_time上建个索引。执行计划从索引leafblock 的最右边开始访问N条记录,再回表N次,效果很好。

过了两天,又来一个需求,需要知道登录次数最多的人是谁。同样的关系型如何处理?DEV说简单

1 select * from login order by login_times desc limit N

DBA一看,又要在login_time上建立一个索引。有没有觉得有点问题呢,表上每个字段上都有素引。

关系型数据库的数据存储的的不灵活是问题的源头,数据仅有一种储存方法,那就是按行排列的堆表。统一的数据结构意味着你必须使用索引来改变sql的访问路径来快速访问某个列的,而访问路径的增加又意味着你必须使用统计信息来辅助,于是一大堆的问题就出现了。

没有索引,没有统计计划,没有执行计划,这就是kv数据库。

redis里如何满足以上的需求呢? 对于求最新的N条数据的需求,链表的后进后出的特点非常适合。我们在上面的登录代码之后添加一段代码,维护一个登录的链表,控制他的长度,使得里面永远保存的是最近的N个登录用户。

1 #把当前登录人添加到链表里
2 ret = r.lpush("login:last_login_times", uid)
3 #保持链表只有N位
4 ret = redis.ltrim("login:last_login_times", 0, N-1)

这样需要获得最新登录人的id,如下的代码即可

1 last_login_list = r.lrange("login:last_login_times", 0, N-1)

另外,求登录次数最多的人,对于排序,积分榜这类需求,sorted set非常的适合,我们把用户和登录次数统一存储在一个sorted set里。

zadd login:login_times 5 1
zadd login:login_times 1 2
zadd login:login_times 2 3

这样假如某个用户登录,额外维护一个sorted set,代码如此

1 #对该用户的登录次数自增1
2 ret = r.zincrby("login:login_times", 1, uid)

那么如何获得登录次数最多的用户呢,逆序排列取的排名第N的用户即可

1 ret = r.zrevrange("login:login_times", 0, N-1)

可以看出,DEV需要添加2行代码,而DBA不需要考虑索引什么的。

TAG系统

tag在互联网应用里尤其多见,如果以传统的关系型数据库来设计有点不伦不类。我们以查找书的例子来看看redis在这方面的优势。

关系型数据库的设计

两张表,一张book的明细,一张tag表,表示每本的tag,一本书存在多个tag。

mysql> select * from book;
+------+-------------------------------+----------------+
| id   | name                          | author         |
+------+-------------------------------+----------------+
|    1 | The Ruby Programming Language | Mark Pilgrim   |
|    1 | Ruby on rail                  | David Flanagan |
|    1 | Programming Erlang            | Joe Armstrong  |
+------+-------------------------------+----------------+

mysql> select * from tag;
+---------+---------+
| tagname | book_id |
+---------+---------+
| ruby    |       1 |
| ruby    |       2 |
| web     |       2 |
| erlang  |       3 |
+---------+---------+

假如有如此需求,查找即是ruby又是web方面的书籍,如果以关系型数据库会怎么处理?
1 select b.name, b.author  from tag t1, tag t2, book b
2 where t1.tagname = 'web' and t2.tagname = 'ruby' and t1.book_id = t2.book_id andb.id = t1.book_id

tag表自关联2次再与book关联,这个sql还是比较复杂的,如果要求即ruby,但不是web方面的书籍呢?

关系型数据其实并不太适合这些集合操作。

REDIS的设计

首先book的数据肯定要存储的,和上面一样。

set book:1:name    ”The Ruby Programming Language”
Set book:2:name     ”Ruby on rail”
Set book:3:name     ”Programming Erlang”

set book:1:author    ”Mark Pilgrim”
Set book:2:author     ”David Flanagan”
Set book:3:author     ”Joe Armstrong”

tag表我们使用集合来存储数据,因为集合擅长求交集、并集

sadd tag:ruby 1
sadd tag:ruby 2
sadd tag:web 2
sadd tag:erlang 3

那么,即属于ruby又属于web的书?

inter_list = redis.sinter("tag.web", "tag:ruby")

即属于ruby,但不属于web的书?

inter_list = redis.sdiff("tag.ruby", "tag:web")

属于ruby和属于web的书的合集?

inter_list = redis.sunion("tag.ruby", "tag:web")

简单到不行阿。

从以上2个例子可以看出在某些场景里,关系型数据库是不太适合的,你可能能够设计出满足需求的系统,但总是感觉的怪怪的,有种生搬硬套的感觉。

尤其登录系统这个例子,频繁的为业务建立索引。放在一个复杂的系统里,ddl(创建索引)有可能改变执行计划。导致其它的sql采用不同的执行计 划,业务复杂的老系统,这个问题是很难预估的,sql千奇百怪。要求DBA对这个系统里所有的sql都了解,这点太难了。这个问题在oracle里尤其严 重,每个DBA估计都碰到过。对于MySQL这类系统,ddl又不方便(虽然现在有online ddl的方法)。碰到大表,DBA凌晨爬起来在业务低峰期操作,这事我没少干过。而这种需求放到redis里就很好处理,DBA仅仅对容量进行预估即可。

未来的OLTP系统应该是kv和关系型的紧密结合。

Redis 键值设计使用总结 阅读详情

相关推荐

59_Redis键值设计

本文围绕 Redis 键值设计,重点阐述了 BigKey 问题及恰当数据类型的运用。BigKey 的判定综合考虑键大小和成员数量,如 String 类型值达 5MB 等情况。其危害严重,读操作易引发网络阻塞,致 Redis 及物理机变慢;造成数据倾斜,使内存资源失衡;对其运算会阻塞 Redis 主线程;序列化反序列化还会增加 CPU 压力。拒绝BigKey

2301_82300081的博客 245

HashMap实例演示---key-value的类型

HashMap实例演示—key-value的类型 前言 对于HashMap的基础学习,相信网上已经有很多很详细的讲解,包括各种深入的源码的分析,各种拓展知识,以及各种和面试官的针锋相对。在这里,我不在进行源码的分析,而是直接用案例向大家演示一下HashMap的实现,让大家带着实际案例学习,我认为这是一个好的学习方式。 一.key为自定义对象,value为String类型 我们知道,HashMap是以key-value类型进行元素存储的集合,而集合里一般是存储对象的,所以我先以自定义对象作为key,Str

baidu_41191295的博客 4179

告别Visual Studio!用MSYS2+GCC+CMake在Windows上打造Linux式C++开发环境(保姆级避坑)

本文详细介绍了如何在Windows上使用MSYS2+GCC+CMake搭建Linux式C++开发环境,替代Visual Studio。从MSYS2的安装配置、MinGW-w64 GCC工具链的部署,到CMake项目的创建与构建,提供了保姆级教程和常见问题解决方案,帮助开发者高效过渡到命令行开发模式。

weixin_30298497的博客 326

关于key-value(键-值对)的用法

/*  * 原则上,一个key对应一个value     但是,我们经常有这样的需求:         湖北省 -> 若干个城市 -> 若干各区县     可以采用变通的方式实现一个key对应多个value(value用集合类型)  */ package com.derun.collection.map;   import java.util.ArrayList; imp

5244

Win11上从零跑通Carla自动驾驶仿真:保姆级环境配置与避坑指南(Python 3.7+)

本文详细介绍了在Win11系统上从零配置Carla自动驾驶仿真环境的完整流程,包括Python 3.7+环境搭建、依赖安装、常见问题排查及性能优化技巧。通过保姆级教程帮助开发者快速避坑,实现稳定的自动驾驶仿真测试环境部署。

weixin_33488239的博客 421

汇川AM402、H3U和上位机C#ModebusTcp通讯

目录一、测试任务二、测试环境三、PLC工程1、组态配置2、ip地址、端口号 3、全局变量定义四、C#端Winform程序创建1创建主界面 2、创建子窗口 3、运行生成,界面效果4、Modebus协议说明5、Modebus操作说明六、测试1、寄存器读测试 2、MW1300寄存器的BIT位3、写寄存器测试4、PLC断电或者断网 七、工程下载连接1、PLC作为ModebusTCP端,端口号都是502,PC端上位机软件作为TcpClient去连接多台PLC。PC端读写PLC寄存器。2、PC端在有的PLC断电、断网的

panjinliang066333的博客 2万+

字典中的key和value的取值规则

1.字典的组成及表示方式 1.1.字典是由许多对相互之间有联系的元素组成,每一对元素都包含一个键(key)和一个值(value)。 这种元素称为键值对,一般记作键:值 (key:value)。 字典的表示方法是,大括号内若干对键值对排列在一起,它们之间用逗号隔开。例子如下:对应的值 1.1.1.1我们可以通过元素的键来获取它的值,也可以添加另外的键值来改动字典,字典型对于键的存储没有特定的顺序。 ...

wangyujie0801_的博客 9099

数学建模灵敏性分析(一阶、二阶灵敏度)python代码+懒人专用版

对于勉强看懂了灵敏度分析的同学来说,本文给出一个方便移植、修改的python程序,可以很方便地进行灵敏度分析。

春江花朝秋月夜 1万+

【Redis】最佳实践——Redis键值设计

Key的最佳实践固定格式:[业务名]:[数据名]:[id]足够简短:不超过44字节不包含特殊字符Value的最佳实践:合理的拆分数据,拒绝BigKey选择合适数据结构Hash结构的entry数量不要超过1000设置合理的超时时间。

奶酪的博客 1980

扩增子分析|基于零模型的群落确定性和随机性构建过程——R实战

周集中教授团队多年在群落确定性和随机性过程深耕,于2017年总结出来下述图表中的计算路径,广受生态领域研究者的推崇。本文基于该计算路径,梳理了整理了邓晔老师组的代码,通过一个实例演示了计算过程和结果。

weixin_46814750的博客 4673

F280049C Crossbar X-BAR

X-BAR不是一个功能模块,只起内部外设与外设之间,或内部外设与GPIO的连接作用。配置X-BAR的就是在配置信号之间的连接。确实如这一节的开头所言,X-BAR提供了以各种配置连接设备输入、输出和内部资源的灵活性。学完这一节也知道为什么crossbar(X-BAR)的中文翻译是交叉开关。

xht2403267701的博客 3048

Redis高级——键值对设计

Key的最佳实践固定格式:[业务名]:[数据名]:[id]足够简短:不超过44字节不包含特殊字符Value的最佳实践:合理的拆分数据,拒绝BigKey选择合适数据结构Hash结构的entry数量不要超过1000设置合理的超时时间。

康小庄的博客 1820

【Matlab光伏功率预测】基于GRU门控循环单元的光伏功率时间序列预测(附MATLAB代码)

【Matlab光伏功率预测】基于GRU门控循环单元的光伏功率时间序列预测(附MATLAB代码)

k8291121的博客 1100

Redis15-Redis键值设计

Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约定: 遵循基本格式:[业务名称]:[数据名]:[id] 长度不超过44字节 不包含特殊字符

m0_73902080的博客 1002

YOLOv13添加轻量化的EMA模块Faster_EMA,轻量又涨点!map50提升4.56个点,召回率提升9.66!

本文介绍了YOLOv13模型的优化移植方法,通过添加Faster_EMA模块和超参数调整,使模型性能显著提升。主要修改包括:1) 创建新的模型配置文件yolov13-Faster_EMA.yaml;2) 在tasks.py中添加新模块;3) 修改__init__.py和block.py文件,新增Partial_conv3和DropPath类。优化后模型mAP50提升4.56%,召回率提升9.66%,验证了改进方案的有效性。代码实现了局部卷积和随机深度等先进技术,为YOLO系列模型性能优化提供了新思路。

FJN110的博客 2606

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

redis键值php,Redis 键值设计问题?

作为一个小白,最近学习 Redis 缓存,心中有一个疑问:假如在 mysql 中有一张 user 表用于保存用户的相关信息,表的主要字段有:id,username,password,email,nick,born,sex,status等等,现在想将 user 数据表中的所有数据全部缓存到 redis 数据库服务器中,请问 redis 的键值应该怎么设置呢?是设为类似于:user:[id]:user...

weixin_39531688的博客 172

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Redis点赞业务的设计与实现(Redis键值设计)

hello你好我是辰兮,很高兴你能来阅读,关于Redis的相关知识我们除了要简单的了解外,还要真正的在项目中实践和应用,本篇是关于Redis点赞的相关具体业务键值设计分享,分享获取新知,大家一起进步! 文章目录一、Redis序言二、Redis点赞 一、Redis序言 一年前就已经接触了Redis的相关知识,了解了这个强大的Redis缓存数据库,接下来会陆续抽时间整理Redis的相关具体应用在电影购票,点赞等相关场景的实现和Redis键值的设计思路,希望自己努力成为一名合格的开发工程师! Redis简.

末尾卡片和博主交流学习! 2900

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Redis:键值设计以及redis优化

批处理,mset只能处理string类型的,而且是原子性的,而pipeline不是原子性的,而mset,hmset这类只能把数据存在同一个key,但是这些都是单机的。可以通过redis中的config get/set hash-max-ziplist-size-entry来查询/设置大小,默认500。spring封装好的方法mset是先用map的key计算出插槽值然后转换成同插槽值得list,然后用异步处理。来检查键值的大小,但是一般不用,因为他对cpu的使用率很高。可以用redis中的。

weixin_73651105的博客 207

Redis高级优化实战:从键值设计到集群调优

本文深入探讨Redis的高级使用技巧和最佳实践。首先介绍了Redis键值设计规范,包括Key结构设计、避免BigKey陷阱及数据类型选择策略。其次详细讲解了批处理性能优化方法,重点分析Pipeline技术和集群环境下的批处理方案。然后从服务端角度提出持久化配置调优、慢查询优化、安全加固和内存优化等策略。最后对比了集群与主从架构的适用场景,并给出集群部署的解决方案。文章强调Redis优化需要从设计、开发和运维多维度综合考虑,建议根据业务特点建立监控体系,持续优化性能。

yh云想的博客 1343

Redis进阶-Redis键值设计及BigKey问题

文章目录键值设计key设计value设计big key的危害命令使用客户端使用其他建议 键值设计 key设计 (1)【建议】: 可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id o2o:order:1 (2)【建议】:简洁性 保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如: user:{uid}...

小工匠 2万+

redis专题:redis键值设计、性能优化以及redis连接池配置

文章目录1.redis键值设计①:key名设计②:value设计2. 命令使用3. redis连接池配置参数设计 1.redis键值设计 redis合理的键值设计,可以增加可读性和可管理性,特别在大型项目中,要特别注意! ①:key名设计 【建议】: 可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id //表示交易系统中的订单号 1 trade:order:1 【建议】:简洁性 保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视

qq_1149513559的博客 2024
上一篇: redis 数据类型详解 以及 redis适用场景场合
下一篇: [ mongoDB ] - 文档型数据库设计模式-如何存储树形数据
codepython
博客等级 码龄20年 125粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值