Redis数据类型及底层实现

文章目录

      • 1.3.1 5种基本数据类型
        • 1.3.1.1 总结篇
        • 1.3.1.2 底层源码引入篇
          • 1.3.1.2.1 redis是字典数据库KV键值对到底是什么
          • 1.3.1.2.2 数据类型视角
          • 1.3.1.2.3 数据模型解析(重点)
          • 1.3.1.2.4 redisObjec
          • 1.3.1.2.5 SDS
        • 1.3.1.3 String
          • 1.3.1.3.1 底层分析
            • 1.3.1.3.1.1 数据结构
            • 1.3.1.3.1.2 源码分析
            • 1.3.1.3.1.3 INT 编码格式(set k1 123)
            • 1.3.1.3.1.4 EMBSTR编码格式(set k1 abc)
            • 1.3.1.3.1.5 raw 编码格式(set k1 大于44长度的一个字符串)
        • 1.3.1.4 Hash
          • 1.3.1.4.1 底层分析
            • 1.3.1.4.1.1 验证编码
            • 1.3.1.4.1.2 源码分析
            • 1.3.1.4.1.3 Ziplist
            • 1.3.1.4.1.4 hashtable
        • 1.3.1.5 List
          • 1.3.1.5.1 底层分析
            • 1.3.1.5.1.1 验证编码
            • 1.3.1.5.1.2 数据结构
            • 1.3.1.5.1.3 源码分析
        • 1.3.1.6 Set
          • 1.3.1.6.1 底层分析
            • 1.3.1.6.1.1 编码验证
            • 1.3.1.6.1.2 数据结构
        • 1.3.1.7 Zset
          • 1.3.1.7.1 底层分析
            • 1.3.1.7.1.1 编码验证
            • 1.3.1.7.1.2 数据结构(skiplist)
            • 1.3.1.7.1.3 源码分析
      • 1.3.2 3种新类型bitmap/hyperloglgo/GEO
        • 1.3.2.1 出现背景分析及统计类型
        • 1.3.2.2 Bitmap
          • 1.3.2.2.1 数据结构
          • 1.3.2.2.2 编码验证
        • 1.3.2.3 Hyperloglog
          • 1.3.2.3.1 计数算法
          • 1.3.2.3.2 HyPerLogLog如何做的?如何演化出来的?
          • 1.3.2.3.3 为什么redis集群的最大槽数是16384个?
          • 1.3.2.3.4 天猫网站首页亿级UV的Redis统计方案
        • 1.3.2.4 GEO
          • 1.3.2.4.1 案例:美团地图位置附近的酒店推送

官网命令大全: http://doc.redisfans.com/,命令不区分大小写,而key是区分大小写的,help @类型名词

1.3.1 5种基本数据类型

程序员写代码时脑子底层思维

总结:

1.3.1.1 总结篇

不同数据类型对应的底层数据结构:
1. 字符串
int:8个字节的长整型。
embstr:小于等于44个字节的字符串。
raw:大于44个字节的字符串。
Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
2. 哈希(ziplist(压缩列表)+hashtable(哈希表))
ziplist(压缩列表):元素个数<512,值长度<64字节,否则,hashtable(哈希表)
ziplist内存连续紧凑,时间换空间,适合内存中数据少的情况
hashtable:读写时间复杂度为O(1)
3.列表(ziplist(压缩列表)+linkedlist(链表))
Ziplist:元素个数<512,值长度<64字节,否则,inkedlist(链表)
4. 集合(intset(整数集合)+hashtable(哈希表))
Intset:元素个数小于512,否则,hashtable
Redis会选用intset来作为集合的内部实现,从而减少内存的使用。
5. 有序集合(ziplist(压缩列表)+skiplist(跳跃表))
ziplist:元素个数<128,元素值长度<64字节,否则,skiplist

1.3.1.2 底层源码引入篇

redis源码在哪里:redis-6.0.8\redis-6.0.8\src

1.3.1.2.1 redis是字典数据库KV键值对到底是什么

redis是key-value存储系统,其中key类型一般为字符串(SDS),value类型则为redis对象(redisObject)

字典、KV是什么:每个键值对都会有一个dictEntry。类比java Map中的Entry

1.3.1.2.2 数据类型视角


上帝视角:
https://redissrc.readthedocs.io/en/latest/datastruct/dict.html
https://redissrc.readthedocs.io/en/latest/index.html

1.3.1.2.3 数据模型解析(重点)

redisObject +Redis数据类型+Redis 所有编码方式(底层实现)三者之间的关系
简单地说,redisObjec就是string、hash、list、set、zset的父类,可以在函数间传递时隐藏具体的类型信息,所以作者抽象了redisObjec结构来到达同样的目的。

1.3.1.2.4 redisObjec

Redis定义了redisObjec结构体来表示string、hash、list、set、zset等数据类型。
Redis 中每个对象都是一个redisObject结构

redisObject结构作用?
其实无论是设计redisObject,还是对存储字符设计这么多的SDS,都是为了根据存储的不同内容(type和encoding字段)选择不同的存储方式,这样可以实现尽量地节省内存空间和提升查询速度的目的。

  1. 4位的type表示具体的数据类型
  2. 4位的encoding表示该类型的物理编码方式见下表,同一种数据类型可能有不同的编码方式。(比如String就提供了3种:int embstr raw)
  3. lru字段表示当内存超限时采用LRU算法清除内存中的对象。
  4. refcount表示对象的引用计数。
  5. ptr指针指向真正的底层数据结构的指针。

编码类型:

Set age 17后redisObjec:

1.3.1.2.5 SDS


Redis中字符串的实现,SDS有多种结构(sds.h)用于存储不同的长度的字符串:
sdshdr5(2^5=32byte)、sdshdr8(2 ^ 8=256byte)、sdshdr16(2 ^ 16=65536byte=64KB)
sdshdr32(2 ^ 32byte=4GB)、sdshdr64(2的64次方byte=17179869184G)。

**len **表示SDS的长度,获取字符串长度O(1),不像C那样需要遍历一遍字符串。
**alloc **用于计算字符串已经分配的未使用的空间,作用:预分配空间的算法,而不用去考虑内存分配的问题。
buf 表示字符串数组,真存数据的。

Redis为什么重新设计一个 SDS 数据结构?
C语言没有Java里面的String类型,redis自己构建了一种名为简单动态字符串 SDS(simple dynamic string)的抽象类型,并将 SDS 作为 Redis 的默认字符串


1.3.1.3 String


1.3.1.3.1 底层分析

1.3.1.3.1.1 数据结构

详见SDS,总结如下:

1.3.1.3.1.2 源码分析

1.3.1.3.1.3 INT 编码格式(set k1 123)

当字符串键值的内容可以用一个64位有符号整形来表示时,Redis会将键值转化为long型来进行存储,此时即对应 OBJ_ENCODING_INT 编码类型。内部的内存结构表示如下:

Redis启动时会预先建立10000个分别存储09999的redisObject变量作为共享对象,这就意味着如果set字符串的键值在010000之间的话,则可以直接指向共享对象而不需要再建立新对象,此时键值不占空间!
set k1 123、set k2 123使用同一块空间

redis源代码:object.c,通过源码说明确实有10000的预分配


1.3.1.3.1.4 EMBSTR编码格式(set k1 abc)

redis源代码:object.c

对于长度小于 44的字符串,Redis 对键值采用OBJ_ENCODING_EMBSTR 方式,EMBSTR 顾名思义即:embedded string,表示嵌入式的String。从内存结构上来讲 即字符串 sds结构体与其对应的 redisObject 对象分配在同一块连续的内存空间,字符串sds嵌入在redisObject对象之中一样。


1.3.1.3.1.5 raw 编码格式(set k1 大于44长度的一个字符串)


当字符串的键值为长度大于44的超长字符串时,Redis 则会将键值的内部编码方式改为OBJ_ENCODING_RAW格式,这与OBJ_ENCODING_EMBSTR编码方式的不同之处在于,此时动态字符串sds的内存与其依赖的redisObject的内存不再连续

1.3.1.4 Hash


1.3.1.4.1 底层分析

1.3.1.4.1.1 验证编码

hash的两种编码格式:ziplist、hashtable
hash-max-ziplist-entries:使用压缩列表保存时哈希集合中的最大元素个数。
hash-max-ziplist-value:使用压缩列表保存时哈希集合中单个元素的最大长度。

采用哪种编码?
Hash类型键的字段个数小于hash-max-ziplist-entries,并且每个字段名和字段值的长度小于hash-max-ziplist-value时,Redis才会使用OBJ_ENCODING_ZIPLIST来存储该键,前述条件任意一个不满足则会转换为OBJ_ENCODING_HT的编码方式

验证:分别先将这两个值设置为3和8

验证上述选择哪种编码的几种情况:


1.3.1.4.1.2 源码分析

编码变化流程:

1.3.1.4.1.3 Ziplist

ziplist.c权威注释:

Ziplist 压缩列表是一种紧凑编码格式,时间换空间的思想,用于字段个数少,且字段值也较小的场景。压缩列表内存利用率极高的原因与其连续内存的特性是分不开的。
想想我们的学过的一种GC垃圾回收机制:标记–压缩算法,当一个hash对象只包含少量键值对且每个键值对的键和值要么就是小整数要么就是长度比较短的字符串,那么它用ziplist作为底层实现
1.3.1.4.1.3.1 压缩列表节点的构成
组成分为三部分:header+entry集合+end,其中header由zlbytes+zltail+zllen组成
zlbytes 4字节,记录整个压缩列表占用的内存字节数。
zltail 4字节,记录压缩列表表尾节点的位置。
zllen 2字节,记录压缩列表节点个数。
zlentry 列表节点,长度不定,由内容决定。
zlend 1字节,0xFF 标记压缩的结束。该字节为255(1111 1111)

压缩列表是 Redis 为节约空间而实现的一系列特殊编码的连续内存块组成的顺序型数据结构,本质上是字节数组

源代码:ziplist.c
ziplist是一个经过特殊编码的双向链表,它不存储指向上一个链表节点和指向下一个链表节点的指针,而是存储上一个节点长度和当前节点长度,通过牺牲部分读写性能,来换取高效的内存空间利用率,节约内存,是一种时间换空间的思想。只用在字段个数少,字段值小的场景里面

zlentry实体结构解析(链表中元素结构)



压缩列表的遍历:(偏移)
通过指向表尾节点的位置指针p1, 减去节点的previous_entry_length,得到前一个节点起始地址的指针。如此循环,从表尾遍历到表头节点。

ziplist存取情况:


1.3.1.4.1.3.2 明明有链表了,为什么出来一个压缩链表?

1.3.1.4.1.4 hashtable

在 Redis 中,hashtable 被称为字典(dictionary),它是一个数组+链表的结构
t_hash.c:

OBJ_ENCODING_HT 编码分析:(每个键值对都会有一个dictEntry)
OBJ_ENCODING_HT 这种编码方式内部才是真正的哈希表结构,或称为字典结构,其可以实现O(1)复杂度的读写操作,因此效率很高。在 Redis内部,从 OBJ_ENCODING_HT类型到底层真正的散列表数据结构是一层层嵌套下去的,组织关系见面图:

源代码:dict.h


1.3.1.5 List


1.3.1.5.1 底层分析

1.3.1.5.1.1 验证编码



1.3.1.5.1.2 数据结构

List的一种编码格式:list用quicklist来存储,quicklist存储了一个双向链表,每个节点都是一个ziplist

(低版本redis:ziplist+linkedList;高版本redis:quicklist+ziplist)

1.3.1.5.1.3 源码分析

quicklist.h
head和tail指向双向列表的表头和表尾

quicklistNode中的*zl指向一个ziplist,一个ziplist可以存放多个元素


1.3.1.6 Set


1.3.1.6.1 底层分析

1.3.1.6.1.1 编码验证


如果元素都是整数类型,就用intset存储,否则用hashtable(数组+链表的存来储结构)。key就是元素的值,value为null。

将配置设置为3,存储元素超过3个编码改变

验证是否改变

1.3.1.6.1.2 数据结构

t_set.c

1.3.1.7 Zset


1.3.1.7.1 底层分析

1.3.1.7.1.1 编码验证

,超过配置阈值,ziplist转化为skiplist
server.zset_max_ziplist_entries:元素个数
server.zset_max_ziplist_value:元素长度

将阈值调小:

1.3.1.7.1.2 数据结构(skiplist)

跳跃表=链表+多级索引,可以实现二分查找的有序链表,空间换时间的结构
说说链表和数组的优缺点?为什么引出跳表


(解决方法:升维,也叫空间换时间)

跳表的时间复杂度:O(logN)
二分查找,时间复杂度是O(logN)
跳表的空间复杂度:O(N)
首先原始链表长度为n
若索引是每2个结点有一个索引结点,每层索引的结点数:n/2, n/4, n/8 … , 8, 4, 2 以此类推;
若每3个结点有一个索引结点,每层索引的结点数:n/3, n/9, n/27 … , 9, 3, 1 以此类推;
所以空间复杂度是O(n);

优缺点
只有在数据量较大的情况下才能体现出来优势。而且应该是读多写少的情况下才能使用,所以它的适用范围应该还是比较有限的

维护成本相对要高 - 新增或者删除时需要把所有索引都更新一遍;
最后在新增和删除的过程中的更新,时间复杂度也是O(log n)

1.3.1.7.1.3 源码分析

t_zset.c:

1.3.2 3种新类型bitmap/hyperloglgo/GEO

1.3.2.1 出现背景分析及统计类型

出现背景:
实现问题:

  1. 手机App中的每天的⽤⼾登录信息:1天对应1系列⽤⼾ID或移动设备ID;
  2. 电商⽹站上商品的⽤⼾评论列表:1个商品对应了1系列的评论;
  3. ⽤⼾在⼿机App上的签到打卡信息:1天对应1系列⽤⼾的签到记录;
  4. 应⽤⽹站上的⽹⻚访问信息:1个⽹⻚对应1系列的访问点击。
  5. 在移动应用中,需要统计每天的新增用户数和第2天的留存用户数;
  6. 在电商网站的商品评论中,需要统计评论列表中的最新评论;
  7. 在签到打卡中,需要统计一个月内连续打卡的用户数;
  8. 在网页访问记录中,需要统计独立访客(UniqueVisitor,UV)量。

痛点:类似今日头条、抖音、淘宝这样的额用户访问级别都是亿级的,请问如何处理?
统计类型:

排序统计案例:
以抖音vcr最新的留言评价为案例,所有评论需要两个功能,按照时间排序+分页显示
能够排序+分页显示的redis数据结构是什么合适?
分析:在⾯对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,建议使⽤ZSet(使用Zset分析此处用户对应的评论条数不会太大)

若是使用list,存在分页数据改变问题(个人感觉能接受,不是什么么问题)


1.3.2.2 Bitmap



1.3.2.2.1 数据结构

由0和1状态表现的二进制位的bit数组,底层String实现

位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(我们可以称之为一个索引或者位格)。Bitmap支持的最大位数是232位,它可以极大的节约存储空间,使用512M内存就可以存储多大42.9亿的字节信息(232 = 4294967296)

案例:京东签到领取京豆(连续签到问题
在签到统计时,每个用户一天的签到用1个bit位就能表示,
一个月(假设是31天)的签到情况用31个bit位就可以,一年的签到也只需要用365个bit位,根本不用太复杂的集合类型

1.3.2.2.2 编码验证

实质是二进制的ascii编码对应,redis里用type命令看看bitmap实质是什么类型???

两个setbit命令对k1进行设置后,对应的二进制串就是0100 0001
二进制串就是0100 0001对应的10进制就是65,所以见下图:

1.3.2.3 Hyperloglog

用途:


1.3.2.3.1 计数算法

去重复统计功能的基数估计算法-就是HyperLogLog

案例:

1.3.2.3.2 HyPerLogLog如何做的?如何演化出来的?

去重复统计你先会想到哪些方式?HashSet、bitmap,优势在于精确。
HashSet存储原始数据,内存消耗大
Bitmap不存储原始数据,消耗比HashSet,随着数据集越大内存消耗也就越大
为解决内存消耗问题,采用概率算法


1.3.2.3.3 为什么redis集群的最大槽数是16384个?

https://github.com/redis/redis/issues/2576

分析:


1.3.2.3.4 天猫网站首页亿级UV的Redis统计方案


分析:
用redis的hash结构存储,按照ipv4的结构来说明,每个ipv4的地址最多是15个字节,某一天的1.5亿15个字节=2G,一个月60G,redis死定了
Hyperloglog:


为什么是12Kb?
每个桶取6位,16384
6÷8 = 12kb,每个桶有6位,最大全部都是1,值就是63

1.3.2.4 GEO

原理:
地理位置信息,地球上的地理位置是使用二维的经纬度表示,核心思想就是将球体转换为平面,区块转换为一点

难点:GeoHash核心原理解析

1.3.2.4.1 案例:美团地图位置附近的酒店推送


选型:es中地理位置信息 或 redis中geo。此处讲述geo
Redis中应该有一份静态数据(如xxx酒店位置),当我们查找会将我们实时位置上传,将附件满足的位置返回给我们(如:xxx酒店)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/353503.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python环境下基于机器学习的NASA涡轮风扇发动机剩余使用寿命RUL预测

本例所用的数据集为C-MAPSS数据集&#xff0c;C-MAPSS数据集是美国NASA发布的涡轮风扇发动机数据集&#xff0c;其中包含不同工作条件和故障模式下涡轮风扇发动机多源性能的退化数据&#xff0c;共有 4 个子数据集&#xff0c;每个子集又可分为训练集、 测试集和RUL标签。其中&…

【Midjourney】内容展示风格关键词

1.几何排列(Geometric) "Geometric" 是一个与几何有关的词汇&#xff0c;通常用于描述与形状、结构或空间几何特征相关的事物。这个词可以涉及数学、艺术、工程、计算机图形学等多个领域。 使用该关键词后&#xff0c;图片中的内容会以平面图形拼接的方式展示&#…

计算机网络——虚拟局域网+交换机基本配置实验

1.实验题目 虚拟局域网交换机基本配置实验 2.实验目的 1.了解交换机的作用 2.熟悉交换机的基本配置方法 3.熟悉Packet Tracer 7.0交换机模拟软件的使用 4.掌握在交换机上划分局域网&#xff0c;并且使用局域网与端口连接&#xff0c;检测信号传输 3.实验任务 1.了解交换…

springboot项目开发,使用thymeleaf前端框架的简单案例

springboot项目开发,使用thymeleaf前端框架的简单案例&#xff01;我们看一下&#xff0c;如何在springboot项目里面简单的构建一个thymeleaf的前端页面。来完成动态数据的渲染效果。 第一步&#xff0c;我们在上一小节&#xff0c;已经提前预下载了对应的组件了。 如图&#x…

phar反序列化漏洞

基础&#xff1a; Phar是一种PHP文件归档格式&#xff0c;它类似于ZIP或JAR文件格式&#xff0c;可以将多个PHP文件打包成一个单独的文件&#xff08;即Phar文件&#xff09;。 打包后的Phar文件可以像普通的PHP文件一样执行&#xff0c;可以包含PHP代码、文本文件、图像等各…

什么叫高斯分布?

高斯分布&#xff0c;也称为正态分布&#xff0c;是统计学中最常见的概率分布之一。它具有钟形曲线的形态&#xff0c;对称分布在均值周围&#xff0c;且由均值和标准差两个参数完全描述。 高斯分布的概率密度函数&#xff08;Probability Density Function, PDF&#xff09;可…

【C++修炼秘籍】Stack和Queue

【C修炼秘籍】STL-Stack和Queue ☀️心有所向&#xff0c;日复一日&#xff0c;必有精进 ☀️专栏《C修炼秘籍》 ☀️作者&#xff1a;早凉 ☀️如果有错误&#xff0c;烦请指正&#xff0c;如有疑问可私信联系&#xff1b; 目录 【C修炼秘籍】STL-Stack和Queue 前言 一、st…

dnSpy调试工具二次开发2-输出日志到控制台

本文在上一篇文章的基础上继续操作&#xff1a; dnSpy调试工具二次开发1-新增菜单-CSDN博客 经过阅读dnSpy的源码&#xff0c;发现dnSpy使用到的依赖注入用了MEF框架&#xff0c;所以在源码中可以看到接口服务类的上面都打上了Export的特性或在构造方法上面打上ImportingConst…

尚无忧球馆助教系统源码,助教小程序源码,助教源码,陪练系统源码

特色功能&#xff1a; 不同助教服务类型选择 助教申请&#xff0c;接单&#xff0c;陪练师入住&#xff0c;赚取外快 线下场馆入住 设置自己服务 城市代理 分销商入住 优惠券 技术栈&#xff1a;前端uniapp后端thinkphp 独立全开源

翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一

随着 OpenAI 在多模态方面的最新进展&#xff0c;想象一下将这种能力与视觉理解相结合。 现在&#xff0c;您可以在 Streamlit 应用程序中使用 GPT-4 和 Vision&#xff0c;以&#xff1a; 从草图和静态图像构建 Streamlit 应用程序。帮助你优化应用的用户体验&#xff0c;包…

NoSQL基本内容

第一章 NoSQL 1.1 什么是NoSQL NoSQL&#xff08;Not Only SQL&#xff09;即不仅仅是SQL&#xff0c;泛指非关系型的数据库&#xff0c;它可以作为关系型数据库的良好补充。随着互联网web2.0网站的兴起&#xff0c;非关系型的数据库现在成了一个极其热门的新领域&#xff0c;…

vulnhub靶场之Five86-2

一.环境搭建 1.靶场描述 Five86-2 is another purposely built vulnerable lab with the intent of gaining experience in the world of penetration testing. The ultimate goal of this challenge is to get root and to read the one and only flag. Linux skills and fa…

2024年阿里云幻兽帕鲁Palworld游戏服务器优惠价格表

自建幻兽帕鲁服务器租用价格表&#xff0c;2024阿里云推出专属幻兽帕鲁Palworld游戏优惠服务器&#xff0c;配置分为4核16G和4核32G服务器&#xff0c;4核16G配置32.25元/1个月、10M带宽66.30元/1个月、4核32G配置113.24元/1个月&#xff0c;4核32G配置3个月339.72元。ECS云服务…

Java项目实战--瑞吉外卖DAY03

目录 P22新增员工_编写全局异常处理器 P23新增员工_完善全局异常处理器并测试 p24新增员工_小结 P27员工分页查询_代码开发1 P28员工分页查询_代码开发2 P22新增员工_编写全局异常处理器 在COMMON新增全局异常捕获的类&#xff0c;其实就是代理我们这些controlle。通过aop把…

【C语言】深入理解指针(3)数组名与函数传参

正文开始——数组与指针是紧密联系的 &#xff08;一&#xff09;数组名的理解 &#xff08;1&#xff09;数组名是数组首元素的地址 int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *parr &arr[0]; 上述代码通过&arr[0] 的方式得到了数组第一个元素的地址&#xff0c;…

基于DataKit迁移MySQL到openGauss

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

RTP工具改进(五)--使用qt

前篇 第四篇 RTP工具改进(四) - rtmp协议推送 前面使用的工具一直为mfc&#xff0c;今天将使用qt 来做界面&#xff0c;使用qt 来进行程序和协议的编写&#xff0c;qt部分目前还不包括rtp ps流和rtmp&#xff0c;暂时只有rtp 直接传输&#xff0c;关于rtmp协议和ps流协议&…

MySQL--创建数据表(5)

创建 MySQL 数据表需要以下信息&#xff1a; 表名表字段名定义每个表字段的数据类型 语法 以下为创建 MySQL 数据表的 SQL 通用语法&#xff1a; CREATE TABLE table_name (column1 datatype,column2 datatype,... );参数说明&#xff1a; table_name 是你要创建的表的名称…

“海洋天堂——助成长计划”走进安徽省科学技术馆

为了助力困境儿童、青少年有效地参与社会生活&#xff0c;培养他们团队精神&#xff0c;引导他们掌握社会规则&#xff0c;增强自信&#xff0c;合肥市庐阳区为民社会工作服务中心于2024年1月24日上午&#xff0c;组织有四名老师带领18名困境儿童、青少年&#xff0c;通过徒步、…

使用PHP自定义一个加密算法,实现编码配合加密,将自己姓名的明文加密一下

<meta charset"UTF-8"> <?phpfunction customEncrypt($lin, $key mySecretKey){// 定义一个简单的替换规则$li array(L > M, I > Y, Y > O, A > N, E > Q, );$yan ;for($i 0; $i < strlen($lin); $i){$char $lin[$i];if(isset($li[…