百搜论坛欢迎您的加入!
adimg adimg
 
昨日:篇  今日:篇   总帖:篇   会员:
今日:0    总帖:10
baby
1020
很多使用了 CRMEB 单商户系统的童鞋在进行二开的时候,都会遇到新建了数据表之后不知道对数据表怎么进行操作。那么,这篇文章将带你完整的实现一遍,以后就不会怕啦。创建数据表就以最简单的为例,创建一个学生的信息表编号姓名性别年龄班级成绩idnamesexageclassscore创建的表为下图所示,其中 id 为数据表自增主键二、创建数据表模型文件程序中创建数据表对应的 model 文件,目录在 app/model 下,该目录下的文件夹是以功能模块进行分类的,我们先创建一个 test 文件夹。创建数据表模型 Student.php 文件。该模型类必须要继承 BaseModel,但是可以不使用 ModelTrait,里面仅实现了三个方法如果不需要的话可以不用引用。然后设置数据表主键protected $pk = 'id';  设置数据表名称protected $name = 'student';  设置完成之后,此 Model 会和数据表进行关联,是程序对表进行操作的重要一个环节创建完成 model 类之后,接下来我们开始完成 Dao 层数据操作的功能实现。二、创建 dao 层数据库操作文件在 app/dao 文件下创建 test 文件夹,并创建 StudentDao.php 的 Dao 层文件。创建完成之后,需要继承 BaseDao,并设置之前创建的 Student 模型protected function setModel(): string   {       return Student::class;   }在这里,我们对数据表的增删改查分别写一个方法,查询分为多条和单条,一共五个方法。使用 $this->getModel() 方法可以获取在上方设置的模型实例化对象,该文件下的所有方法都可以使用此方法进行模型的实例化,新增数据时,使用 $this->getModel()->save($data); 即可实现数据的新增逻辑,$data 为想要新增的数据,数组类型。对于数据的查询,分为单条和多条查询,我们在这里分为两个方法去实现。同理使用$this->getModel()->where($where)->find(); 可以实现单条查询的逻辑,$where 是查询的条件,例如:$where = [‘name’=>’张三’],这个条件就是查询 name 姓名为张三的数据对象。如果使用主键进行单条查询,可以直接使用 $this->get($id) 的方法获取。多条数据查询,如果不分页的情况下,写法和单条一样,只是将 find() 改为 select(),如果需要分页查询需要传入 page 和 limit(当前页数和每页条数)然后进行分页查询其中 when 判断了当 page 和 limit 传入的数据都大于 0 的时候才会进行分页查询,如果传入 0 或者不传,则默认查询全部的数据。修改数据,修改数据需要传入一个条件和一个需要修改的数组变量,根据条件去修改对应的数据,$where 负责查询对应的数据,将对应的数据修改成 $data 里面携带的参数,注意,$where 和 $data 里面的数组键必须是数据表里面存在的字段,此方法可以修改单条或者多条,取决于 $where 的查询是单条还是多条,会返回被修改的数据条数。删除数据,如果数据表里面设置的删除的字段,可以使用修改的方法将字段进行修改做到软删除,如果需要直接删除数据,则可是使用 delete() 方法。三、创建 services 层数据处理文件在 app/services 文件下创建 test 文件夹,并创建 StudentServices.php 的 services 层文件。创建完成之后,需要继承 BaseServices,并注入 StudentDao本次我们不对数据做任何处理,只是实现数据表的增删改查所以,在 services 文件中可以直接写好对应的调用,也可以不用写对应的方法,系统会自动找到 dao 层的方法进行处理创建控制器以及路由文件路由文件增加对应五个方法的路由,添加,查询单条,查询多条,修改,删除对应控制器中的五个方法,控制器需要先注入 StudentServices,才能使用 services 中的方法,控制器中,获取参数使用 request 中的 getMore 或者 postMore 来获取,到此调用对应的接口,就可以实现数据库简单的增删改查了。总结:CRMEB 系统中,每个层级是非常清楚的,controller 用来接受和发送数据,services 用来组合数据逻辑处理,dao 层是用来对数据库的增删改查,model 是数据库的模型类,弄懂了这些逻辑和文件层级,以后在在开发中会更方便和快捷。可以对照附件研究学习,有遇到不懂不明白之处可以在下方留言源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27提取码: yu27百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~GIT 项目推荐:包含多端免授权可商用附件地址:http://github.crmeb.net/u/defu
0 0 607天前
baby
1078
首先,商家需要在微信后台申请自定义版交易组件权限,申请成功后,可以将小程序关联至对应视频号,并在视频号带货直播中使用。申请开通商户号等商户号审核之后在操作一下步骤接口调用(pro 为例)实例代码商品接口调用(https://api.weixin.qq.com/shop/spu/add)添加完商品等到微信审核,审核过后下单购买打开微信开发者工具点进个商品详情,id 是商品 id,场景值选择 1177正常下单购买流程(https://api.weixin.qq.com/shop/order/add)同步物流,(https://api.weixin.qq.com/shop/delivery/send)创建售后(https://api.weixin.qq.com/shop/ecaftersale/add)同意退款(https://api.weixin.qq.com/shop/ecaftersale/acceptrefund)小程序公众号平台依次点击完成即可上传审核小程序,等小程序发布之后,视频号推广审核十一、场景接入前往微信公众平台中,进入 “交易组件”>“场景接入” 菜单中,查看并选择需要接入的场景,微信官方默认所有场景均可接入。视频号对接的讲解就到这里结束了,大家有不懂的地方可以在下方留言源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27提取码: yu27百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~GIT 项目推荐:包含多端免授权可商用附件地址:https://gitee.com/ZhongBangKeJi
0 0 608天前
baby
1350
运行下面就以 crmeb-java 开源版代码为例,首先下载源码包【附件在最下面】Java 代码运行 (运行基础环境和单商户的一致)运行条件 jdk 1.8maven 环境 3.3.xmysql 5.7redis 最新即可Node 版本 14+npm 版本 8.0+crmeb-admin  管理端物业代码包,包含平台和商户,需要部署。crmeb-front 商城代码包 需要部署crmeb-common  公共代码包 应用到 crmeb-admin 和 crmeb-front 中 不用部署crmeb-service 公共业务代码代码包 需要部署配置 Mysql 和 Redis 链接数据库脚本在代码包中 启动前导入。邮箱服务配置管理端 API 说明,点击左上角选择平台端和商户端 api平台管理端代码启动配置环境为上一步启动的 java 服务这里可能有些朋友会出错,无论 npm install 还是 cnpm install 只要你能安装成功就好node 版本 14+npm 版本 8.0+npm 启动成功后,会自动打开浏览器,如果启动失败 需要重复上面的 npm install 操作,执行之前手动删除 vue 代码根目录下的 node_modules 文件夹平台端登录成功注意:商户平台商户端代码包和平台端类似 设置和启动方式也一致,配置后启动即可,下图为商户端启动成功页面和登录后页面。移动端商城启动H5 使用 Hbuilder X 加载移动端代码需要在 java 代码中启动 crmeb-front 程序第一次运行有不懂不明白之处可以在下方留言源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27提取码: yu27百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~GIT 项目推荐:包含多端免授权可商用附件地址:https://gitee.com/ZhongBangKeJi
0 0 608天前
baby
1148
前端数据结构参照:https://github.com/StavinLi/Workflow数据表结构:数据处理:/**  * 处理流程配置  * @param $type  * @param $data  * @return mixed  */ public function checkProcessConfig($data, $type = 'processConfig') {     if (!isset($data[$type]) || !$data[$type])         return [];     return $this->getSerializeData($data[$type]); } /**  * 初始化流程配置数据  * @param $data  * @param int $level  * @param string $onlyValue  * @param int $is_initial  * @return array  */ public function getSerializeData($data, $level = 0, $onlyValue = '', $is_initial = 1, $group = 0) {     $info[] = $this->getInfo($data, $onlyValue, $level, $is_initial, $group);     if ($data['childNode']) {         $level++;         if (isset($data['childNode'])) $info = array_merge($info, $this->getSerializeData($data['childNode'], $level, $data['onlyValue'], 0, $group));     }     if (isset($data['conditionNodes']) && $data['conditionNodes']) {         foreach ($data['conditionNodes'] as $v) {             $group++;             $level++;             $info[] = $this->getInfo($v, $data['onlyValue'], $level, 0, $group);             if ($v['childNode']) {                 $info = array_merge($info, $this->getSerializeData($v['childNode'], $level, $v['onlyValue'], 0, $group));             }         }     }     return $info; } /**  * 组合流程数据  * @param $data  * @param string $parent  * @param int $level  * @param int $is_initial  * @param int $group  * @return array  */ public function getInfo($data, $parent = '', $level = 0, $is_initial = 0, $group = 0) {     return [         //节点名称(申请人、审核人、抄送人)         'name'           => $data['nodeName'],         //节点类型:0、申请人;1、审核人;2、抄送人;3、条件;4、路由;         'types'          => $data['type'],         'uniqued'        => $data['onlyValue'],//节点唯一值         //审核人类型:1、指定成员;2、指定部门主管;7、连续多部门;5、申请人自己;4、申请人自选;(0、无此条件)         'settype'        => isset($data['settype']) && $data['settype'] ? $data['settype'] : 0,         //指定层级顺序:0、从上至下;1、从下至上;(-1、无此条件)         'director_order' => isset($data['directorOrder']) ? $data['directorOrder'] : -1,         //指定主管层级/指定终点层级:1-10;(0、无此条件)         'director_level' => isset($data['directorLevel']) && $data['directorLevel'] ? $data['directorLevel'] : 0,         //当前部门无负责人时:1、上级部门负责人审批;2、为空时跳过;(0、无此条件)         'no_hander'      => isset($data['noHanderAction']) && $data['noHanderAction'] ? $data['noHanderAction'] : 0,         //可选范围:1、不限范围;2、指定成员;(0、无此条件)         'select_range'   => isset($data['selectRange']) && $data['selectRange'] ? $data['selectRange'] : 0,         //指定的成员列表         'user_list'      => isset($data['nodeUserList']) && $data['nodeUserList'] ? $data['nodeUserList'] : [],         //选人方式:1、单选;2、多选;(0、无此条件)         'select_mode'    => isset($data['selectMode']) && $data['selectMode'] ? $data['selectMode'] : 0,         //多人审批方式:1、或签;2、会签;3、依次审批;(0、无此条件)         'examine_mode'   => isset($data['examineMode']) && $data['examineMode'] ? $data['examineMode'] : '',         //条件优先级         'priority'       => isset($data['priorityLevel']) && $data['priorityLevel'] ? $data['priorityLevel'] : 0,         'parent'         => $parent,//父级唯一值         'level'          => $level,         'info'           => $is_initial > 0 ? $data : [],         'is_initial'     => $is_initial,         'is_child'       => $data['childNode'] ? 1 : 0,         'is_condition'   => isset($data['conditionNodes']) && $data['conditionNodes'] ? 1 : 0,         'card_id'        => $this->cardId,         'groups'         => $group,         'entid'          => $this->entId(false),         'condition_list' => isset($data['conditionList']) ? $data['conditionList'] : [],         //指定部门负责人         'dep_head'       => isset($data['departmentHead']) ? $data['departmentHead'] : [],         //是否允许自选抄送人         'self_select'    => isset($data['ccSelfSelectFlag']) ? $data['ccSelfSelectFlag'] : 0,     ]; }数据处理完成后保存数据库即可。思路:利用节点唯一值绑定节点的上下级关系,使用层级区分节点层级深度。源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27 提取码: yu27百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~开源地址码云地址:http://github.crmeb.net/u/defuGithub 地址:http://github.crmeb.net/u/defu
0 0 619天前
baby
1276
后疫情时代,数字化跨境电商脱颖而出,成为增速最快的对外贸易方式,社交电商、短视频、直播带货,纷纷开始进入跨境电商市场,呈现出一派欣欣向荣的景象。为助力更多商家打造私有化外贸商城平台,CRMEB 审时度势,勇敢探索,开发出 Java 多商户外贸版商城系统。该系统支持多商户入驻经营,适配多种语言、多种跨境电商必备功能,接下来就来仔细了解一下吧!基础功能1、支持多语言切换CRMEB Java 多商户外贸版商城系统支持中文、英文、法语等多语言切换,基础标签可以根据选择进行语言转换(更多语言持续更新中...)。2、登录方式多样系统提供有 6 种登录方式,可以使用邮箱账号、手机号登陆平台,也支持 Twitter、Facebook、Google 等第三方账号授权登录,还可以匿名登录平台购买商品。3、对接第三方 API成功对接阿里国际短信、阿里国际物流、IP 定位第三方 API,打通跨境电商运营全链路,让跨境购物更加快捷、便利。4、商品管理平台商品由平台进行统筹管理,平台和商户都可以设置管理商品分类,同时,在商品评论中,平台可以添加虚拟评论,支持商户回复评论,还能够查询评论列表数据,帮助平台和商户进行商品数据分析。5、订单管理客户可在平台一次性跨店购买多件商品,下单后会实时分单至商户后台,在此期间形成店铺流水、账单;订单发送货使用阿里国际物流。6、消息通知消息通知有邮箱通知和短信通知两种类型,邮箱和短信都是使用阿里云的服务,分别是阿里云企业邮箱和国外及港澳台消息。短信使用前必须开启对应服务并且根据已经存在的短信模板进行申请,商户消息签名可以根据自己的实际需求来进行设置。7、客服系统系统配置有 4 种客服方式,分别是蚂蚁云智服、邮箱客服、电话客服和 Messager 客服。8、商户入驻平台中设有商户入驻入口,商户通过填写店铺信息、上传相关资质、同意入驻协议提交后等待平台审核,平台审核后会以短信通知的方式告知申请者结果,审核实时状态可以在移动端商户入驻查询。9、财务功能该系统具备常用的财务功能,所有商户的交易资金会首先保存在平台账户,平台会向商户收取一定比例的手续费,商户可以在后台发起提现申请,提现所得货款。营销功能1、商户优惠券系统设置有商户优惠券,用户可领取使用商户优惠券,让平台店铺营销更具吸引力。2、平台营销活动平台首页设置有精品推荐、热门榜单、首发新品、促销单品等营销活动,增加平台活动营销筹码,吸引消费者注意,在推动营销的同时,将消费者引流至店铺,扩大店铺影响力。工欲善其事,必先利其器。国际贸易全球化发展势头强劲,跨境电商数字化日新月异,外贸电商系统面临着新的考验与挑战。CRMEB Java 多商户外贸版商城系统的诞生,是恰逢其时也是大势所趋,我们会牢牢把握时代的发展机会,用好产品、好品质、好服务,让用户满意,让自己成长! 源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27 提取码: yu27百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~开源地址码云地址:https://gitee.com/ZhongBangKeJi/crmeb_javaGithub 地址:https://gitee.com/ZhongBangKeJi/crmeb_java
0 0 633天前
baby
1121
Java 语言融合面向对象、分布式、健壮性、安全性、多线程、动态性等特点于一身,使其在各个领域应用的非常广泛,也因其更靠近底层,造成开发周期长,开发成本高等问题,不是任何个人开发者能承担的起,并有能力去做的一件事。CRMEB 因为开源,一步步走到今天,也获得了无数用户的支持,此刻 CRMEB 有能力去回馈更多用户,自然不会吝啬分毫,用户的需求才是 CRMEB 前进的方向,不让 “悉察用户需求,精益求精,超越用户期待” 的服务理念成为一句空话,Java 版单商户系统全开源不加密,所有功能都开源,为用户创造价值,利他也将永远深耕在众邦的心里,开源也更加体现出众邦人的利他态度和社会责任。CRMEB Java 单商户 v1.3 版本功能亮点:1、技术栈SpringBoot+Maven+Swagger+MybatisPlus+Redis+Uniapp+Vue+ElementUi2、前后端分离开发,多端数据同步uniapp 开发,包含移动端,公众号,小程序,PC 后台,Api 接口;3、后台管理系统模块包含:产品、用户、购物车、订单、积分、优惠券、营销、余额、权限、角色、系统设置、组合数据、可拖拉拽的 form 表单等,营销功能包含砍价、拼团、秒杀、会员等,并且全开源,大量减少大家重复造轮子的时间,二开更简单。4、开源项目内包含三个子项目admin - WEB 程序 - PC 端管理端 VUE + ElementUiapp - 移动商城 - UniApp 标准开发crmeb - Api - Java SpringBoot + mybatisPlus ...icons - 基本素材 - 分类图标等接口文档 - Api 对应的接口文档也可以部署项目后查看 5、主要特性有详细的代码注释,有完整系统手册6、SpringBoot 框架使用 SpringBoot 框架框架开发前端采用 Vue UniApp 框架前端使用 Vue UniApp 框架,标准前后端分离开发8、标准接口标准 RESTful 接口、逻辑层次更明确接口文档自动生成9、支持队列降低流量高峰,解除耦合,高可用10、无缝事件机制行为扩展更方便,方便二次开发11、数据操作Excel 数据导出,导出表格更加美观可视;12、数据统计分析后台使用 ECharts 图表统计,实现用户、产品、订单、资金等统计分析13、强大的后台权限管理后台多种角色、多重身份权限管理,权限可以控制到每一步操作14、表单生成器可以自由拖拉拽配置表单,减少前端重复表单工作量,后端接口统一调用用互联网技术助力企业发展永远是我们矢志不渝的理想,我们会倾尽全力为这个理想而奋斗不已,您的 Star 是我们源源不断开源的动力。源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27 提取码: yu27百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~开源地址码云地址:https://gitee.com/ZhongBangKeJi/crmeb_javaGithub 地址:https://gitee.com/ZhongBangKeJi/crmeb_java
0 0 633天前
admin
976
在使用 Redis 的过程中,你是否遇到过下面这些问题:开启 RDB 落盘,业务频繁出现请求超时。除了 save 和 bgsave 命令,还有哪些操作会触发 RDB 落盘?执行了 flushall,发现 flushall 之前写的数据又冒出来了。重启 Redis 实例之后,发现数据有丢失的情况。带着上面这些问题,我们一起来聊聊 RDB 的一些细节。触发 RDB 文件创建的命令有两条,save 和 bgsave。save 我们知道会阻塞整个实例,通常也不太可能会用。bgsave 命令是在后台生成 RDB 文件,Redis 仍然可以处理客户端请求。但是并不能保证 bgsave 不会影响 Redis 所有的客户端请求,在生成 RDB的过程中,Redis 会 fork 出一个子进程,子进程和父进程会共享内存地址空间,可以保证子进程拥有父进程相同的内存数据。但是在 fork 子进程时,操作系统需要将父进程的内存页表复制给子进程。如果整个 Redis 实例占用的内存很大,那么它的内存页表也会很大,复制的时间也会比较长。同时,这个过程会消耗大量的 CPU 资源,在复制完成之前,父进程也会被阻塞,无法处理客户端请求。执行 fork 后,子进程可以扫描 Redis 中所有数据,然后将所有数据写入 RDB 文件。之后,父进程仍然处理客户端的请求。父进程在处理写命令时,会重新分配新的内存地址空间,向操作系统申请新的内存使用,不再与子进程共享。这样,父子进程的内存会逐渐分离,父进程会申请新的内存空间并改变内存数据,子进程的内存数据不会受到影响。可以看出,在生成RDB文件时,不仅消耗CPU资源,还需要消耗更多的内存空间。上面也就是“开启 RDB 落盘,业务频繁出现请求超时”的原因。通常在生产环境,我们也应该避免在 master 实例上做 RDB。那么除了 save 和 bgsave 命令,还有哪些常见会触发 RDB 呢?这里就来总结几种情况,这也是问题“除了 save 和 bgsave 命令,还有哪些操作会触发 RDB 落盘呢?”的答案:1 配置了 RDB 落盘的情况比如配置文件配置了 save xxx xxx,或者命令行执行了 config set save "xxx xxx",都表示配置了 RDB 落盘。比如配置了 save 900 1则表示 900 秒内如果至少有 1 个 key 的值变化,则做一次 bgsave。我们在前面有提到 bgsave 也会对客户端请求有所影响,所以不建议在 master 上增加该参数,如果为了数据备份,建议只在 slave 增加 save 参数。2 主从复制第一次创建主从复制关系时,会在主库执行 bgsave 命令生成 RDB 文件,然后传给从库,从库加载 RDB 文件,以完成一次全量数据的传输。因此在业务访问高峰,并且数据量比较大的情况,不建议在 master 上创建 slave。3 Redis 在执行 flushall 命令配置了 RDB 落盘的情况,在执行 flushall 命令时,会进行一次 RDB 落盘,但是内容是空的。目的是将 RDB 文件也清空。但是,如果 RDB 和 AOF 都关闭的情况下,会有下面这种情况:127.0.0.1:6301> set aaa 111OK127.0.0.1:6301> set bbb 111OK127.0.0.1:6301> bgsaveBackground saving started127.0.0.1:6301> flushallOK127.0.0.1:6301> config get save"save"""127.0.0.1:6301> config get appendonly"appendonly""no"127.0.0.1:6301> shutdown再启动 Redis127.0.0.1:6301> keys *"aaa""bbb"会看到我们清空 Redis 之前写入的数据。显然是不符合逻辑的。这是因为在启动 Redis 时,会加载数据目录下的 RDB 文件,而这个 RDB 文件是 flushall 之前执行 bgsave 生成的,也就是会看到清空 Redis 之前写入的数据。这里也是“执行了 flushall,发现 flushall 之前写的数据又冒出来了”的原因。所以在实例未开启 RDB 和 AOF 的情况下,如果执行 了 flushall 命令,建议再执行一次 bgsave,让 RDB 文件也清空。另外还测试了开启 AOF,关闭 RDB 的情况:127.0.0.1:6301> set aaa 111OK127.0.0.1:6301> set bbb 111OK127.0.0.1:6301> bgsaveBackground saving started127.0.0.1:6301> flushallOK127.0.0.1:6301> config get save"save"""127.0.0.1:6301> config get appendonly"appendonly""yes"127.0.0.1:6301> shutdown启动 Redis127.0.0.1:6301> keys *(empty list or set)重启之后不会再看到 flushall 之前写入的数据,因为 Redis 在 启动时加载 RDB 文件后,也会加载在执行 RDB 之后 AOF 里新增的操作。而 flushall 操作就记录在 AOF 文件中。4 正常关闭时我们通过在命令行执行 shutdown 正常关闭 Redis 时,并不是所有情况都会执行一次 RDB 落盘的,这里就来分析一下不同配置,重启后的情况。4.1 AOF 和  RDB 都开启的情况127.0.0.1:6301> set bbb 111OK127.0.0.1:6301> config get save"save""1800 1"127.0.0.1:6301> config get appendonly"appendonly""yes"127.0.0.1:6301> shutdown启动 Redis127.0.0.1:6301> get bbb"111"这种情况会在关闭时执行一次 RDB 落盘,启动时加载 RDB 文件,保证重启前后数据一致。4.2 AOF 和 RDB 都未开的情况127.0.0.1:6301> set ccc 111OK127.0.0.1:6301> config get save"save"""127.0.0.1:6301> config get appendonly"appendonly""no"127.0.0.1:6301> shutdown然后启动 Redis127.0.0.1:6301> get ccc(nil)发现重启之前 ccc 的 key 已经丢失,因此在 master 未开启 RDB 的情况,关闭之前需要主动执行 bgsave,否则会导致数据丢失。这也是“重启 Redis 实例之后,发现数据有丢失的情况”的原因。4.3 AOF 关闭,RDB 开启的情况127.0.0.1:6301> set ddd 111OK127.0.0.1:6301> config get save"save""1800 1"127.0.0.1:6301> config get appendonly"appendonly""no"127.0.0.1:6301> shutdown启动 Redis127.0.0.1:6301> get ddd"111"这种情况会写 RDB,重启后数据未丢失。4.4 AOF 开启,RDB 关闭的情况127.0.0.1:6301> set eee 111OK127.0.0.1:6301> config get save"save"""127.0.0.1:6301> config get appendonly"appendonly""yes"127.0.0.1:6301> shutdown启动 Redis127.0.0.1:6301> get eee"111"这种情况尽管不会进行 RDB 落盘,但是因为之前的操作都写入了 AOF,在 Redis 启动时,会加载 AOF 里的数据,因此也会跟关闭之前的数据保持一致。
0 0 661天前
admin
981
一、目标任务首先要明确的是, 作为了一个每天在 Linux Server 上 rm -rf 的人来说, 如果想在 Mac 上使用 Docker, 最舒服的也是兼容所有 docker cli 命令行操作即可; 至于图形化的界面完全不需要, 我们并不指望图形化界面能比敲命令快到哪里去, 也不指望图形化界面变为主力; 所以本篇文章的核心目标:在 Mac 上使用完整的 docker cli 命令, 包括对基本的 -v 挂载支持可以支持 x86 的模拟, 可以为 x86 build 或者运行相关镜像在尽可能的情况下可以进行 CPU 架构切换, arm64 与 x86 最好都可以支持二、工具选型首先是我们最熟悉的 Docker Desktop, 安装包奇大无比, UI 卡成翔, 启动速度更不用提而且还时不时的卡死, 所以 Docker Desktop 是完全不考虑的; 那么剩下几种方案类型如下:VM 虚拟机方案Colima 方案Lima 方案先说结论: Lima YES! VM 虚拟机方案要花钱且难受, Colima 暂且不稳定. Lima 方案直接看第五节.三、虚拟机方案目前在 M1 上, 唯一可用或者说堪用的虚拟机当属 Parallels Desktop, 至于其他的 VBox、VMware 目前还不成熟; 如果纯 qemu 有点过于硬核(愿意自己封装脚本的当我没说); 对于 Parallels Desktop 来说, 我们需要购买开发版本的 License, 因为我们需要借助 prlctl 来实现一些自动化 , 一年好几百… 经过测试这种方案也有一定可行性:1、首先通过 PD 创建 Ubuntu 之类的虚拟机2、在虚拟机里安装好 Docker3、通过 cli 程序启动虚拟机, 并且将 ~ rw 挂载到虚拟机里基于这个方案我个人尝试过, 曾经写过一个 PD 的小工具来辅助完成挂载动作. 但是这种工具有一些明显的缺点:目前不支持 x86 的模拟, 可通过 binfmt 缓解, 但是不完善虚拟机要花钱且需要虚拟机 cli 支持完善四、Colima 方案Colima 号称是专门为了解决 Mac 平台容器化工具链的, 但是实际测试发现目前 Colima 还不算稳定, 有时可能会有一些小问题; 当然 Colima 最大的问题是: 可自定义化程度不高, 底层基于 Lima. Colima 具体的使用方式啥的这里暂不详细描述, 目前还不稳定不太推荐.五、Lima 方案Lima 目前是基于 QEMU 的自动化 VM 方案, 当前由于其出色设计, 借助 Cloud Init 可以在很多阶段帮助我们完成 hook; 所以不论是装个 Docker 还是 k8s, 亦或是弄个其他的东西都很方便; 而且很多方案比如 docker 官方都有相关样例, 我们可以直接照抄外加做点自定义.5.1、Lima 安装Lima 在 Mac 下安装相对简单, 以下命令将安装 master 分支版本.brew install lima --HEAD在正常情况下, 安装 Lima 会附带安装 QEMU, 如果本机已经安装 QEMU, 可能需要执行以下命令将 QEMU 升级到 7.0:brew upgrade qemu为了使用 docker, 还需要通过 brew 安装一下 docker cli:brew install docker5.2、Lima 使用默认情况下 Lima 安装完成后会生成一个 lima 的快捷命令, 目前不太推荐使用, 原因是看起来方便一点但是没法控制太多参数, 所以仍然建议使用标准的 limactl 命令进行操作. limactl 使用方式如下:Lima: Linux virtual machinesUsage:  limactl [command]Examples:  Start the default instance:  $ limactl start  Open a shell:  $ lima  Run a container:  $ lima nerdctl run -d --name nginx -p 8080:80 nginx:alpine  Stop the default instance:  $ limactl stop  See also example YAMLs: /opt/homebrew/share/doc/lima/examplesAvailable Commands:  completion    Generate the autocompletion script for the specified shell  copy          Copy files between host and guest  delete        Delete an instance of Lima.  edit          Edit an instance of Lima  factory-reset Factory reset an instance of Lima  help          Help about any command  info          Show diagnostic information  list          List instances of Lima.  prune         Prune garbage objects  shell         Execute shell in Lima  show-ssh      Show the ssh command line  start         Start an instance of Lima  stop          Stop an instance  sudoers       Generate /etc/sudoers.d/lima file for enabling vmnet.framework support  validate      Validate YAML filesFlags:      --debug     debug mode  -h, --help      help for limactl  -v, --version   version for limactlUse "limactl [command] --help" for more information about a command.Copy5.3、Lima 配置文件Lima 通过读取一个 yaml 配置描述文件来决定如何创建一个虚拟机, 该文件基本结构如下:# 定义每个平台架构需要使用的启动镜像images:- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"  arch: "x86_64"- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"  arch: "aarch64"# 定义虚拟机需要使用哪个架构启动(对应上面的镜像)arch: "x86_64"# CPU 数量cpus: 4# 内存大小memory: "16G"# 磁盘大小disk: "100G"# 虚拟机与 macOS 宿主机挂载时使用的挂载技术# 目前推荐 9p, 可换成 sshfs, 但是 sshfs 会有权限问题mountType: 9p# 定义虚拟机和 macOS 宿主机有哪些目录可以共享mounts:- location: "~"  # 定义虚拟机对这个目录是否可写  writable: true  9p:    # 对于可写的共享目录, cache 推荐类型为 mmap, 不写好像默认 fscache    cache: "mmap"- location: "/tmp/lima"  writable: true  9p:    cache: "mmap"# containerd is managed by Docker, not by Lima, so the values are set to false here.containerd:  system: false  user: false# cloud-init hook 定义provision:# 定义以什么权限在虚拟机内执行脚本- mode: system  # This script defines the host.docker.internal hostname when hostResolver is disabled.  # It is also needed for lima 0.8.2 and earlier, which does not support hostResolver.hosts.  # Names defined in /etc/hosts inside the VM are not resolved inside containers when  # using the hostResolver; use hostResolver.hosts instead (requires lima 0.8.3 or later).  script: |    #!/bin/sh    sed -i 's/host.lima.internal.*/host.lima.internal host.docker.internal/' /etc/hosts- mode: system  script: |    #!/bin/bash    set -eux -o pipefail    if command -v docker >/dev/null 2>&1; then      docker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install all      exit     else      export DEBIAN_FRONTEND=noninteractive      curl -fsSL https://get.docker.com | sh      docker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install all      # NOTE: you may remove the lines below, if you prefer to use rootful docker, not rootless      systemctl disable --now docker      apt-get install -y uidmap dbus-user-session    fi- mode: user  script: |    #!/bin/bash    set -eux -o pipefail    systemctl --user start dbus    dockerd-rootless-setuptool.sh install    docker context use rootlessprobes:- script: |    #!/bin/bash    set -eux -o pipefail    if ! timeout 30s bash -c "until command -v docker >/dev/null 2>&1; do sleep 3; done"; then      echo >&2 "docker is not installed yet"      exit 1    fi    if ! timeout 30s bash -c "until pgrep rootlesskit; do sleep 3; done"; then      echo >&2 "rootlesskit (used by rootless docker) is not running"      exit 1    fi  hint: See "/var/log/cloud-init-output.log". in the guesthostResolver:  # hostResolver.hosts requires lima 0.8.3 or later. Names defined here will also  # resolve inside containers, and not just inside the VM itself.  hosts:    host.docker.internal: host.lima.internalportForwards:- guestSocket: "/run/user/{{.UID}}/docker.sock"  hostSocket: "{{.Dir}}/sock/docker.sock"# 自己定义的启动后消息输出message: |  To run `docker` on the host (assumes docker-cli is installed), run the following commands:  ------  docker context create amd64 --docker "host=unix://{{.Dir}}/sock/docker.sock"  docker context use amd64  ------Copy5.4、启动 VMlimactl 命令提供了一个 start 子命令用于启动一个虚拟机, 子命令接受一个参数, 这个参数形式不同会产生不同的行为:如果参数为一个文件路径, 则假定文件为一个 lima 虚拟机的 yaml 配置, 读取并启动如果参数是单纯字符串, 首先尝试从已存在的虚拟机中查找名字相同的, 找到则立即启动如果参数是单纯字符串, 且未找到已存在同名的虚拟机, 则尝试通过内置模版来创建一个新的虚拟机以上面我自己定义的 docker 配置文件为例, 我们直接启动这个配置既可以创建一个 docker 虚拟机:limactl start ./docker-amd64.yaml启动后会提示是否编辑然后再启动, 这是为了使用同一个配置来启动多个 vm 使用的, 所以不编辑直接启动即可:稍等片刻后虚拟机将启动成功:启动完成后, 执行最下面打印出的两条命令, 即可在宿主机上完整的使用 docker. 其本质上利用 docker context 功能, 然后通过将虚拟机中的 sock 文件挂载到宿主机, 并配置 docker context 来实现无缝使用 docker 命令.5.5、虚拟机调整某些情况下, 我们需要定制一些 VM 里的配置, 在定制时主要需要调整配置文件的 provision 部分; 在该部分中, 如果 mode 被定义为 system 则会以 root 用户执行相关命令, 否则以普通用户来执行命令. 需要注意的是, 我们定义的脚本需要具有幂等性, 因为脚本在每次都会执行一次, 所以一般对于可能造成数据擦除动作的命令都要写好判断逻辑, 避免重复执行.关于文件挂载, 这里推荐使用 9p 类型, 未来 lima 将完全切换到该挂载方式; 同时经过测试目前仅有 9p 挂载模式下, 本地目录 rw 映射到虚拟机时不会出现权限问题, sshfs 方式挂载如果遇到 chown 之类的命令会造成权限错误, 可能导致容器启动失败(例如 mysql).在测试虚拟机配置过程中, 可以直接使用 limactl delete -f xxxx 来强制删除目标虚拟机, 然后重新启动即可; 虚拟机名称默认与 yaml 文件名相同, 可使用 limactl ls 命令查看.5.6、多平台兼容在上面我的 docker 配置样例中, 每次虚拟机启动完成后会自动安装 binfmt:docker run --platform=linux/amd64 --privileged --rm tonistiigi/binfmt --install all这样能保证无论 Lima 虚拟机原始架构是什么, 都能运行其他平台的 docker 镜像; 典型的例如某些 openjdk8 镜像只有 amd64 的版本, 但是在 lima 虚拟机为 aarch64 的情况下仍然可以使用.除了这种 “速度较快” 的跨架构运行方式, lima 还支持直接在 VM 中定义架构, 这样在 qemu 启动时则会直接从 VM 系统层模拟目标架构; 这种方式的好处是对目标架构兼容性很好, 但是运行速度会更慢. 调整 VM 架构只需要修改 arch 配置即可(注意, 目标架构的镜像一定要配置好):# 定义每个平台架构需要使用的启动镜像images:- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img"  arch: "x86_64"- location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"  arch: "aarch64"# 定义本虚拟机需要使用哪个架构启动(对应会使用上面目标架构的镜像)arch: "aarch64"Copy六、总结目前整体来看, Docker Desktop 在 mac 上基本上是很难用的, Colima 现在还不太成熟, 适合轻度使用 docker 的用户; 而重度使用 docker 并且有定制化需求的用户还是推荐 Lima 虚拟机; 同时 Lima 也支持很多操作系统, 官方有大量的样例模版(包括 k8s、k3s、podman 等), 非常适合重度容器使用者.
0 0 667天前
admin
1168
执行 php think swoole restart 命令的时候,提示 [Swoole\Exception]  failed to listen server port[0.0.0.0:8324], Error: Address already in use[98] 这个是服务器的 8324 端口被占用了。1、首先确定服务器上只有一套多商户代码,或者是没有其他地方用到了 8324端口;进入命令行执行以下命令。如何进入命令行点这里  ps aux | grep swoole | awk '{print $2}' | xargs kill -9 执行了以后,在重启swoole就可以了;2、 如果服务器上有其他的项目使用了此端口,修改一下此项目的运行端口,然后重启swoole即可。如何修改运行端口号点这里
0 0 668天前
admin
1025
一、抽象类和接口选择的 “陷阱” 在设计一个类时如何选择 抽象类 和 接口? 设计实现一个 GigaFactory 类, 对 GigaFactory 的拆分既不能全部是抽象类,也不能全部是抽象接口,比如产能如果定义在接口里面就是一个常量,每个 GigaFactory 工厂的产能是不同的,这样就失去了每个对象的状态信息。 那可以都定义为抽象类吗? 也不能将功能都拆分为抽象类,会导致代码难以维护,这是从代码的灵活性和复杂性考虑的。从语言特性来考虑也不合适,类是对事物的客观抽象,并不是所有的类都具有相同的行为。 可以将共同的属性使用抽象类来表达,比如状态等,而将特有的行为使用接口定义,每个不同的类实现特定的接口。 新建 Maven 项目 abstract-interface-traps,增加 entity 包,定义一个 Factory 抽象类/** * 每个 Factory 最基本的属性 */ public abstract class Factory { protected String address; protected Integer productivity; } 复制代码复制定义生产整车业务的接口类 Vehicle/** * 整车业务生产,Model 3、Y、X 等 */ public interface Vehicle { void produceCars(); } 复制代码复制定义生产配件的接口类/** * 配件业务生产,电机等 */ public interface Autoparts { void makeParts(); } 复制代码复制定义生产太阳能业务的接口类 Energy/** * 太阳能业务 */ public interface Energy { void produceSolarPanels(); } 复制代码复制定义一个上海超级工厂类,继承 Factory 类,实现整车业务接口类 Vehiclepublic class ShanghaiGigaFactory extends Factory implements Vehicle{ protected String address = "Shanghai"; protected Integer productivity = 500000; @Override public void produceCars() { } }复制源码附件已经打包好上传到百度云了,大家自行下载即可~链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27 提取码: yu27 百度云链接不稳定,随时可能会失效,大家抓紧保存哈。如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~开源地址 码云地址: http://github.crmeb.net/u/defuGithub 地址: http://github.crmeb.net/u/defu
1 0 669天前
快速发帖 高级模式
联系站长 友链申请桂ICP备19000949号-1     桂ICP备19000949号-1
您的IP:3.141.100.120,2024-04-19 14:31:34,Processed in 0.20625 second(s).
免责声明: 本网不承担任何由内容提供商提供的信息所引起的争议和法律责任。
Powered by HadSky 7.12.9
免责声明
1、本站资源,均来自网络,版权归原作者,所有资源和文章仅限用于学习和研究目的 。
2、不得用于商业或非法用途,否则,一切责任由该用户承担 !
如果觉得本文还不错请点个赞或者打赏点轻币哦~
拒绝伸手党,拿走请回复,尊重楼主,尊重你我他~

侵权删除请致信 E-Mail:207882320@qq.com